I have a problem: In a bigger project with a similar structure I am getting a memory Leak from the Instrument Tool.
If you are putting this in Xcode and run, you should see a line which is moving to the right side and then to the left.
When the Button is pressed, the Line jumps to a defined position.
If you use the Memory Leak Tool there is an Error after the Button is tapped. I don’t know why. Is this a bug? Do I have a basic mistake in the code? How to avoid this?
Is this the right way of connecting the animation calculation with SwiftUI, that I have the SKScene as an ObservableObject and mark the animation as @Published for doing this animation?
I appreciate any answers.
In the leakage Tool is a note, that the responsible frame is:
[NSXPCConnection remoteObjectProxyWithErrorHandler:]
Thanks for reading, here is the example code:
Overview
Animation Calc
import SwiftUI
import SpriteKit
struct MyAnimation{
var lenght:CGFloat = 0 //Position of the line end
var up: Bool = true //if the line is moving to right or left
mutating func change(){
self.up ? (lenght += 1) : (lenght -= 1)
if lenght > 100{
up = false
}else if lenght < 0{
up = true
}
}
}
SKScene for updating
class GameScene: SKScene, ObservableObject{
@Published var ani: MyAnimation //handles the calculation
override init(){
ani = MyAnimation()
super.init(size: CGSize(width: 200, height: 100))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func update(_ currentTime: TimeInterval) {
ani.change() //new Position is calculated
}
}
Content View
struct ContentView: View {
@StateObject var game = GameScene()
var body: some View {
VStack{
ZStack{
SpriteView(scene: game).opacity(0)
MyPath().environmentObject(game)
}
Start().environmentObject(game)
//Button to let the line jump to the defined position
}
}
}
Path to animate
struct MyPath: View{
@EnvironmentObject var game: GameScene
var body: some View{
Path{ path in
path.move(to: CGPoint(x: 50, y: 50))
path.addLine(to: CGPoint(x: 200 + game.ani.lenght, y: 220))
//here is the length property of the MyAnimation struct and should cause the redraw
path.closeSubpath()
}
.stroke(Color.black, lineWidth: 4)
}
}
Button
struct Start: View { //Button
@EnvironmentObject var game: GameScene
var body: some View {
Button(action: {
game.isPaused = true
game.ani.lenght = 30
game.isPaused = false
}, label: {
Text("Start")
})
}
}
For Copy Paste
import SwiftUI
import SpriteKit
struct MyAnimation{
var lenght:CGFloat = 0 //Position of the line end
var up: Bool = true //if the line is moving to right or left
mutating func change(){
self.up ? (lenght += 1) : (lenght -= 1)
if lenght > 100{
up = false
}else if lenght < 0{
up = true
}
}
}
class GameScene: SKScene, ObservableObject{
@Published var ani: MyAnimation //handles the calculation
override init(){
ani = MyAnimation()
super.init(size: CGSize(width: 200, height: 100))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func update(_ currentTime: TimeInterval) {
ani.change() //new Position is calculated
}
}
struct ContentView: View {
@StateObject var game = GameScene()
var body: some View {
VStack{
ZStack{
SpriteView(scene: game).opacity(0)
MyPath().environmentObject(game)
}
Start().environmentObject(game)
//Button to let the line jump to the defined position
}
}
}
struct MyPath: View{
@EnvironmentObject var game: GameScene
var body: some View{
Path{ path in
path.move(to: CGPoint(x: 50, y: 50))
path.addLine(to: CGPoint(x: 200 + game.ani.lenght, y: 220))
//here is the length property of the MyAnimation struct and should cause the redraw
path.closeSubpath()
}
.stroke(Color.black, lineWidth: 4)
}
}
struct Start: View { //Button
@EnvironmentObject var game: GameScene
var body: some View {
Button(action: {
game.isPaused = true
game.ani.lenght = 30
game.isPaused = false
}, label: {
Text("Start")
})
}
}
2
Answers
I could reproduce the same leak with the following code:
Without having more insights into this issue, I would assume that you are not responsible for the leak, but Apple is.
I think you have no choice but to ignore the leak for now if you still wish to use SwiftUI.
By the way, I had worse issues with SwiftUI, and I have abandoned it for now because I believe it just isn’t ready yet.
I solved it by using NotificationCenter to update my skscene
in swiftUI View: