Swift 4:从Popover ViewController实时更新SceneKit调试选项求助
解决SceneKit DebugOptions实时更新的方案
嘿,我来帮你搞定这个实时更新SceneKit调试选项的问题!你之前用UserDefaults、委托协议没生效,核心原因是状态变化后没有立刻触发主ViewController里SceneView的debugOptions属性更新——重启生效只是因为启动时读取了存储的配置,但运行中状态变了却没触发刷新。
具体实现步骤
1. 给Popover VC加个闭包回调(比协议更轻量好用)
在你的Popover ViewController里,加一个闭包用来传递开关状态变化,这样开关一动就能立刻通知主VC:
class PopoverViewController: UIViewController { // 示例开关,你可以换成自己的多个开关 @IBOutlet weak var showWireframeSwitch: UISwitch! // 定义闭包,用来传递最终的调试选项集合 var debugOptionsChanged: ((SCNDebugOptions) -> Void)? override func viewDidLoad() { super.viewDidLoad() // 初始化开关状态,从UserDefaults读之前存的值 let isWireframeOn = UserDefaults.standard.bool(forKey: "ShowWireframe") showWireframeSwitch.isOn = isWireframeOn } @IBAction func switchToggled(_ sender: UISwitch) { // 先把状态存到UserDefaults,避免重启丢失 UserDefaults.standard.set(sender.isOn, forKey: "ShowWireframe") // 计算当前应该启用的调试选项 var currentOptions = SCNDebugOptions() if showWireframeSwitch.isOn { currentOptions.insert(.showWireframe) } // 这里可以加其他开关对应的选项,比如.showBoundingBox、.showConstraints等 // 触发闭包,把新选项传给主VC debugOptionsChanged?(currentOptions) } }
2. 在主VC里绑定闭包,实时更新SceneView
在你弹出Popover的地方(比如prepare(for:sender:)方法),给Popover VC设置闭包,直接修改SceneView的debugOptions——这一步是实时生效的关键:
extension ViewController { override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let popoverVC = segue.destination as? PopoverViewController else { return } // 设置闭包,一旦Popover里的开关变化,立刻更新SceneView的调试选项 popoverVC.debugOptionsChanged = { [weak self] newOptions in guard let self = self else { return } // 直接赋值,马上就能看到效果! self.sceneView.debugOptions = newOptions } } }
3. 主VC启动时初始化调试状态
别忘了在主VC启动时,从UserDefaults读取之前的配置,初始化SceneView的状态:
class ViewController: UIViewController { @IBOutlet weak var sceneView: SCNView! override func viewDidLoad() { super.viewDidLoad() setupInitialDebugSettings() } private func setupInitialDebugSettings() { var initialOptions = SCNDebugOptions() if UserDefaults.standard.bool(forKey: "ShowWireframe") { initialOptions.insert(.showWireframe) } // 初始化其他选项 sceneView.debugOptions = initialOptions } }
为啥之前的方法没效果?
- 如果用了UserDefaults但没监听变化:UserDefaults默认不会主动通知状态变更,除非你加
UserDefaults.didChangeNotification监听,但闭包回调更直接,没必要绕弯。 - 如果用了协议但没生效:大概率是代理对象没正确设置,或者协议方法调用时机不对,闭包在这种简单的跨VC状态传递场景下,出错概率低很多。
小提示
- 要是有多个调试开关,直接把所有开关的状态组合成一个
SCNDebugOptions集合传递就行,不用单个传布尔值,更灵活。 - 闭包里用
[weak self]是为了避免循环引用,防止内存泄漏哦。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

