SwiftUI下SpriteView承载的SKScene touchesBegan仅识别首次触摸问题
SwiftUI 中 SpriteView 承载 SKScene 无法处理多点触控的解决方案
问题根源
- 系统默认的
SpriteView底层封装的SKView实例默认未开启多点触控(isMultipleTouchEnabled属性为false),系统只会将单个触摸事件传递给场景的touchesBegan方法,因此多手指同时触摸时只有第一个手指的操作会被响应;而你在UIKit的UIViewController中使用原生SKView时通常会手动开启该属性,因此功能正常。 - 原代码中
scene是计算属性,每次视图body刷新都会重新创建GameScene实例,会导致场景被意外重建,属于冗余隐患。
解决方案
步骤1:自定义支持多点触控的SpriteView包装器
SwiftUI没有提供直接修改SpriteView内部SKView配置的原生方法,我们通过UIViewRepresentable包装原生SKView,手动开启多点触控能力:
import SwiftUI import SpriteKit struct MultiTouchSpriteView: UIViewRepresentable { let scene: SKScene func makeUIView(context: Context) -> SKView { let skView = SKView() // 核心配置:开启多点触控 skView.isMultipleTouchEnabled = true // 加载场景 skView.presentScene(scene) return skView } func updateUIView(_ uiView: SKView, context: Context) { // 场景无动态更新时无需额外处理 } }
步骤2:修改ContentView的场景初始化逻辑
将原计算属性的scene改为仅初始化一次的状态属性,避免场景被反复重建,同时替换原系统SpriteView为自定义包装器:
struct ContentView: View { // 仅初始化一次的游戏场景,避免body刷新时重建 @State private var gameScene: GameScene = { let scene = GameScene() scene.size = CGSize(width: 500, height: 350) scene.scaleMode = .fill return scene }() var body: some View { MultiTouchSpriteView(scene: gameScene) .frame(width: 500, height: 350) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
说明
- 原
GameScene的代码无需修改,其touchesBegan逻辑本身适配多点触控,和UIKit下的表现一致。 - 修改后同时触摸左右半区时,会分别生成对应颜色的方块,完全符合预期。
内容的提问来源于stack exchange,提问作者AcmeCat
相关产品推荐
相关产品推荐

