如何使用SwiftUI的SpriteView(isPaused:)暂停SKScene且不重复初始化
问题根因
场景反复重建的核心原因并非isPaused参数使用错误,而是当前代码中scene为计算属性,每次SwiftUI因showingLevelChooser状态变化重绘视图时,都会重新生成全新的GameScene实例,导致计时器清零。
解决方案
使用@State修饰符持有GameScene实例,保证它在视图生命周期内仅初始化一次即可,修改后的ContentView代码如下:
struct ContentView: View { @State private var showingLevelChooser = false // @State持有场景实例,仅初始化一次 @State private var scene: GameScene = { let scene = GameScene() scene.size = CGSize(width: 300, height: 400) scene.anchorPoint = CGPoint(x: 0.5, y: 0.5) scene.scaleMode = .fill return scene }() var body: some View { ZStack { SpriteView(scene: scene, isPaused: showingLevelChooser) .ignoresSafeArea() VStack { Button("Level Chooser") { showingLevelChooser.toggle() } Spacer() } } .sheet(isPresented: $showingLevelChooser) { VStack { Button("Cancel") { showingLevelChooser.toggle() } Text("Level Chooser") } } } }
原理解释
@State修饰的引用类型会在SwiftUI的视图生命周期中保持同一个实例,不会随body重绘反复生成。此时传入isPaused参数,SwiftUI只会更新SpriteView的暂停状态,不会触发场景重建,游戏计时会在弹窗关闭后继续累计。
如果场景需要在多视图间共享,也可以将其放到符合ObservableObject协议的视图模型中,通过@StateObject持有视图模型即可。
内容的提问来源于stack exchange,提问作者clns
相关产品推荐
相关产品推荐

