【问题标题】:SpriteKit and SwiftUI Animation (Memory Leak - NSXPCConnection?)SpriteKit 和 SwiftUI 动画(内存泄漏 - NSXPCConnection?)
【发布时间】:2021-08-04 04:22:56
【问题描述】:

我有一个问题:在一个结构相似的大型项目中,我从仪器工具中发现内存泄漏。

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

这是将动画计算与 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, 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")
            })
        }
    }

【问题讨论】:

  • 它可能是无害的,应该不足以让你的应用崩溃。除非它导致您可以看到的问题,否则请忽略它。

标签: ios swift xcode swiftui sprite-kit


【解决方案1】:

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

  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 时遇到了更严重的问题,我暂时放弃了它,因为我相信它还没有准备好。

【讨论】:

  • 谢谢。我的工具现在不能工作,但我希望这个问题能很快得到解决。
猜你喜欢
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 2016-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多