如何从SpriteKit的SKScene场景中弹出展示SwiftUI视图
从SpriteKit场景弹出SwiftUI视图的实现方案
推荐实现方案(状态驱动,全SwiftUI风格)
因为你的SKScene本身是由SwiftUI视图承载的,最符合SwiftUI声明式编程规范的方式是通过状态变量控制弹窗显隐,完全不用手写UIKit的addSubview逻辑。
步骤1:修改SKScene子类,添加交互回调
在你的SKScene子类中新增回调属性,替换原来的视图添加/移除逻辑:
class GameScene: SKScene { // 新增回调,用于通知SwiftUI层切换弹窗显隐状态 var toggleInstructionsPopUp: (() -> Void)? // 保留你原有的其他属性定义... // 原有触摸检测逻辑修改如下 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let location = touches.first?.location(in: self) else { return } if bloqsLogo.contains(location) { // 直接调用回调,把显隐控制逻辑交给SwiftUI层处理 toggleInstructionsPopUp?() } } }
步骤2:在承载SKScene的SwiftUI视图中添加状态控制
定义状态变量控制弹窗显隐,同时给SKScene的回调赋值:
struct GameHostView: View { // 控制指令弹窗显隐的状态变量 @State private var showInstructions = false // 实例化你的SKScene private let gameScene: GameScene = { let scene = GameScene(size: CGSize(width: 1080, height: 1920)) scene.scaleMode = .aspectFill return scene }() var body: some View { ZStack { // 承载SpriteKit游戏场景 SpriteView(scene: gameScene) .ignoresSafeArea() } // 绑定状态,直接用SwiftUI原生组件渲染弹窗 .sheet(isPresented: $showInstructions) { // 这里传入你开发的SwiftUI版弹窗视图即可 InstructionsPopUp() } .onAppear { // 给SKScene的回调赋值,触发时切换显隐状态 gameScene.toggleInstructionsPopUp = { showInstructions.toggle() } } } }
该方案的优势:
- 所有UI逻辑都用SwiftUI实现,符合你的技术栈要求
- 不需要手动管理视图的添加/移除、tag标记,避免内存泄漏风险
- 可以直接使用SwiftUI的
sheet、popover、自定义overlay等任意弹窗样式
备选方案(兼容UIKit加Subview的写法)
如果你要沿用原有的addSubview逻辑,需要把SwiftUI视图用UIHostingController包装后再添加:
if bloqsLogo.contains(location) { if instructionsOn == false { // 把SwiftUI视图包装成UIKit可识别的视图 let hostingVC = UIHostingController(rootView: InstructionsPopUp()) hostingVC.view.tag = 104 hostingVC.view.frame = self.view?.bounds ?? .zero hostingVC.view.backgroundColor = .clear self.view?.addSubview(hostingVC.view) instructionsOn = true } else { if let viewWithTag = self.view!.viewWithTag(104) { viewWithTag.removeFromSuperview() instructionsOn = false } else { print("nah") } } }
注意该方案需要手动处理UIHostingController的生命周期,避免内存泄漏,更推荐使用第一种状态驱动的方案。
内容的提问来源于stack exchange,提问作者Waterboy
相关产品推荐
相关产品推荐

