SwiftUI WatchOS 8应用:如何处理数码表冠旋转不刷新视图?
解决方案
1. 用ViewModel稳定持有GameScene实例
通过@StateObject创建ViewModel来托管GameScene,确保场景实例在视图生命周期内只初始化一次,不会随视图刷新重建:
import SwiftUI import SpriteKit class GameViewModel: ObservableObject { let gameScene: GameScene init() { // 根据WatchOS屏幕尺寸初始化场景 self.gameScene = GameScene(size: CGSize(width: 136, height: 172)) gameScene.scaleMode = .resizeFill } }
2. 在GameScene中添加精灵旋转控制方法
在你的GameScene类里,直接写一个修改精灵角度的方法,脱离SwiftUI状态依赖:
class GameScene: SKScene { let targetSprite = SKSpriteNode(imageNamed: "your-sprite") override func didMove(to view: SKView) { // 初始化精灵的基础逻辑(位置、物理属性等) targetSprite.position = CGPoint(x: size.width/2, y: size.height/2) addChild(targetSprite) } // 接收表冠旋转值,直接更新精灵角度 func adjustSpriteRotation(rotation: Double) { // 这里可调整系数适配表冠灵敏度,把旋转值转成弧度 targetSprite.zRotation = CGFloat(rotation) * .pi / 180 } }
3. 自定义Binding传递表冠旋转值
不用@State触发视图刷新,而是创建自定义Binding,在set方法里直接调用GameScene的旋转控制方法,让表冠操作只作用于精灵,不触发视图重载:
struct WatchGameView: View { @StateObject private var viewModel = GameViewModel() var body: some View { SpriteView(scene: viewModel.gameScene) .digitalCrownRotation( Binding( get: { 0 }, // 无需依赖状态,返回固定值即可 set: { newRotation in // 直接把表冠旋转值传给场景 viewModel.gameScene.adjustSpriteRotation(rotation: newRotation) } ), from: 0, through: 360, by: 1, sensitivity: .low, isContinuous: true, isHapticFeedbackEnabled: true ) } }
方案核心逻辑
@StateObject保证ViewModel和GameScene实例唯一,彻底避免场景因视图刷新重启;- 自定义
Binding绕过SwiftUI的状态刷新机制,表冠操作只会通知GameScene修改精灵,不会触发整个视图重建; - 精灵旋转逻辑完全在SpriteKit层处理,和SwiftUI状态解耦,不影响其他游戏逻辑运行。
内容的提问来源于stack exchange,提问作者dmjman
相关产品推荐
相关产品推荐

