SpriteKit 和 SwiftUI 动画(内存泄漏 - NSXPCConnection?) [英] SpriteKit and SwiftUI Animation (Memory Leak - NSXPCConnection?)
问题描述
我遇到了一个问题:在具有类似结构的更大项目中,我从仪器工具中获得内存泄漏.
如果你把它放在 Xcode 中并运行,你应该看到一条向右移动然后向左移动的线.当按下 Button 时,Line 跳转到定义的位置.如果您使用内存泄漏工具,点击按钮后会出现错误.我不知道为什么.这是一个错误吗?我在代码中有一个基本错误吗?如何避免这种情况?
这是将动画计算与 SwiftUI 连接起来的正确方法吗,我将 SKScene 作为 ObservableObject 并将动画标记为 @Published 以执行此动画?
感谢您的回答.
在泄漏工具中有一个注释,负责的框架是:
[NSXPCConnection remoteObjectProxyWithErrorHandler:]
感谢阅读,示例代码如下:概述
动画计算
导入 SwiftUI导入 SpriteKit结构我的动画{var lenght:CGFloat = 0//行尾位置var up: Bool = true//如果线条向右或向左移动变异 func change(){自我提升?(长度 += 1) : (长度 -= 1)如果长度 >100{向上 = 假}否则如果长度<0{向上 = 真}}}
更新SKScene
<预><代码>类 GameScene:SKScene,ObservableObject{@Published var ani: MyAnimation//处理计算覆盖初始化(){ani = 我的动画()super.init(size: CGSize(width: 200, height: 100))}需要初始化?(编码器aDecoder:NSCoder){fatalError(init(coder:) 尚未实现")}覆盖 func 更新(_ currentTime:TimeInterval){ani.change()//计算新位置}}内容视图
<预><代码>结构内容视图:查看{@StateObject var game = GameScene()var主体:一些视图{虚拟堆栈{ZStack{SpriteView(场景:游戏).不透明度(0)MyPath().environmentObject(游戏)}开始().环境对象(游戏)//按钮让线条跳到定义的位置}}}动画路径
<预><代码>结构我的路径:查看{@EnvironmentObject var 游戏:GameScenevar body: 一些视图{路径{路径在path.move(to: CGPoint(x: 50, y: 50))path.addLine(to: CGPoint(x: 200 + game.ani.lenght, y: 220))//这里是 MyAnimation 结构的长度属性,应该导致重绘path.closeSubpath()}.stroke(颜色.黑色,线宽:4)}}按钮
<预><代码>struct Start: View {//按钮@EnvironmentObject var 游戏:GameScenevar主体:一些视图{按钮(动作:{game.isPaused = 真game.ani.lenght = 30game.isPaused = 假}, 标签: {文本(开始")})}}用于复制粘贴
导入 SwiftUI导入 SpriteKit结构我的动画{var lenght:CGFloat = 0//行尾位置var up: Bool = true//如果线条向右或向左移动变异 func change(){自我提升?(长度 += 1) : (长度 -= 1)如果长度 >100{向上 = 假}否则如果长度<0{向上 = 真}}}类 GameScene:SKScene,ObservableObject{@Published var ani: MyAnimation//处理计算覆盖初始化(){ani = 我的动画()super.init(size: CGSize(width: 200, height: 100))}需要初始化?(编码器aDecoder:NSCoder){fatalError(init(coder:) 尚未实现")}覆盖 func 更新(_ currentTime:TimeInterval){ani.change()//计算新位置}}结构内容视图:查看{@StateObject var game = GameScene()var主体:一些视图{虚拟堆栈{ZStack{SpriteView(场景:游戏).不透明度(0)MyPath().environmentObject(游戏)}开始().环境对象(游戏)//按钮让线条跳到定义的位置}}}结构我的路径:查看{@EnvironmentObject var 游戏:GameScenevar body: 一些视图{路径{路径在path.move(to: CGPoint(x: 50, y: 50))path.addLine(to: CGPoint(x: 200 + game.ani.lenght, y: 220))//这里是 MyAnimation 结构的长度属性,应该导致重绘path.closeSubpath()}.stroke(颜色.黑色,线宽:4)}}struct Start: View {//按钮@EnvironmentObject var 游戏:GameScenevar主体:一些视图{按钮(动作:{game.isPaused = 真game.ani.lenght = 30game.isPaused = 假}, 标签: {文本(开始")})}}
我可以使用以下代码重现相同的泄漏:
导入 SwiftUI结构内容视图:查看{var主体:一些视图{虚拟堆栈{开始()}}}结构开始:查看{var主体:一些视图{按钮(动作:{}, 标签: {文本(开始")})}}
如果没有对这个问题有更深入的了解,我会假设您不对泄漏负责,但 Apple 是.
如果您仍然希望使用 SwiftUI,我认为您现在别无选择,只能忽略泄漏.
顺便说一下,我在使用 SwiftUI 时遇到了更严重的问题,我暂时放弃了它,因为我认为它还没有准备好.
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")
})
}
}
I could reproduce the same leak with the following code:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack{
Start()
}
}
}
struct Start: View {
var body: some View {
Button(action: {
}, label: {
Text("Start")
})
}
}
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.
这篇关于SpriteKit 和 SwiftUI 动画(内存泄漏 - NSXPCConnection?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!