SpriteKit 和 SwiftUI 动画内存泄漏 - NSXPCConnection?

问题描述

我遇到了一个问题:在具有类似结构的更大项目中,我从仪器工具中获得内存泄漏。

如果你把它放在 Xcode 中并运行,你应该看到一条向右移动然后向左移动的线。 当按下 Button 时,Line 跳转到定义的位置。 如果您使用内存泄漏工具,点击按钮后会出现错误。我不知道为什么。这是一个错误吗?我在代码中有一个基本错误吗?如何避免这种情况?

这是将动画计算与 SwiftUI 连接起来的正确方法吗,我将 SKScene 作为 ObservableObject 并将动画标记为 @Published 以执行此动画?

感谢您的回答。

在泄漏工具中有一个注释,负责的框架是:

[nsxpcconnection remoteObjectProxyWithErrorHandler:]

感谢阅读,示例代码如下: 概述

动画计算

    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


    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")
            })
        }
    }

用于复制粘贴

    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,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,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")
            })
        }
    }

解决方法

我可以使用以下代码重现相同的泄漏:

  import SwiftUI

  struct ContentView: View {
    var body: some View {
        VStack{
            Start()
        }
    }
  }

  struct Start: View {
    var body: some View {
        Button(action: {
        },label: {
            Text("Start")
        })
    }
  }

如果没有对这个问题有更深入的了解,我会假设您不对泄漏负责,但 Apple 是。

如果您仍然希望使用 SwiftUI,我认为您现在别无选择,只能忽略泄漏。
顺便说一下,我在使用 SwiftUI 时遇到了更严重的问题,我暂时放弃了它,因为我认为它还没有准备好。