Swift 4.0跨类调用方法:如何在WheelDelegate触发Main控制器方法
解决转轮停止后调用视图控制器方法的问题
我来帮你搞定这个问题——要在转轮的角速度降为0时,调用Main视图控制器里的methodToCall方法,核心是建立WheelDelegate和Main之间的通信关联。下面给你三种iOS开发中常用的实现方案,你可以根据自己的项目架构选择最合适的:
方案一:代理模式(推荐,耦合度低且易维护)
代理模式是组件间通信的经典方式,适合这种一对一的回调场景:
- 首先定义一个代理协议,用来声明转轮停止的回调方法:
protocol WheelStopDelegate: AnyObject { func wheelDidStopRotating() }
- 修改
WheelDelegate,添加一个弱引用的代理属性,并在转轮停止时调用代理方法:
class WheelDelegate: NSObject, SKSceneDelegate { // 用weak修饰避免循环引用 weak var stopDelegate: WheelStopDelegate? func didSimulatePhysics(for scene: SKScene) { guard let wheelScene = scene as? WheelScene else { return } let angularVelocity = wheelScene.wheel.physicsBody?.angularVelocity ?? 0.0 if angularVelocity > 0.0 { print(angularVelocity) if angularVelocity < 25.0 { wheelScene.wheel.physicsBody?.angularVelocity = 0.0 // 转轮停止时通知代理 stopDelegate?.wheelDidStopRotating() } } } }
- 让
Main视图控制器遵守这个代理协议,并实现回调方法:
class Main: UIViewController, WheelStopDelegate { func methodToCall() { print("METHOD CALLED") } // 假设你在这里初始化WheelDelegate实例 let wheelDelegate = WheelDelegate() override func viewDidLoad() { super.viewDidLoad() // 设置代理为当前控制器 wheelDelegate.stopDelegate = self // 记得把wheelDelegate绑定到SKScene的delegate上 // 比如:yourSKScene.delegate = wheelDelegate } // 实现代理方法,调用目标函数 func wheelDidStopRotating() { methodToCall() } }
方案二:闭包回调(简洁灵活)
闭包是更轻量化的回调方式,代码更紧凑:
- 在
WheelDelegate中添加一个可选闭包属性:
class WheelDelegate: NSObject, SKSceneDelegate { // 定义闭包类型,用来接收停止事件 var onWheelStop: (() -> Void)? func didSimulatePhysics(for scene: SKScene) { guard let wheelScene = scene as? WheelScene else { return } let angularVelocity = wheelScene.wheel.physicsBody?.angularVelocity ?? 0.0 if angularVelocity > 0.0 { print(angularVelocity) if angularVelocity < 25.0 { wheelScene.wheel.physicsBody?.angularVelocity = 0.0 // 触发闭包回调 onWheelStop?() } } } }
- 在
Main控制器中初始化WheelDelegate时,给闭包赋值:
class Main: UIViewController { func methodToCall() { print("METHOD CALLED") } let wheelDelegate = WheelDelegate() override func viewDidLoad() { super.viewDidLoad() // 用[weak self]避免循环引用 wheelDelegate.onWheelStop = { [weak self] in self?.methodToCall() } // 绑定到SKScene的delegate // yourSKScene.delegate = wheelDelegate } }
方案三:通知中心(适合跨多个组件的场景)
如果你的项目中需要多个地方监听转轮停止事件,可以用通知中心:
- 先定义一个自定义通知名称:
extension Notification.Name { static let wheelDidStopRotating = Notification.Name("WheelDidStopRotating") }
- 在
WheelDelegate中发送通知:
class WheelDelegate: NSObject, SKSceneDelegate { func didSimulatePhysics(for scene: SKScene) { guard let wheelScene = scene as? WheelScene else { return } let angularVelocity = wheelScene.wheel.physicsBody?.angularVelocity ?? 0.0 if angularVelocity > 0.0 { print(angularVelocity) if angularVelocity < 25.0 { wheelScene.wheel.physicsBody?.angularVelocity = 0.0 // 发送转轮停止的通知 NotificationCenter.default.post(name: .wheelDidStopRotating, object: nil) } } } }
- 在
Main控制器中监听通知并处理:
class Main: UIViewController { func methodToCall() { print("METHOD CALLED") } override func viewDidLoad() { super.viewDidLoad() // 添加通知观察者 NotificationCenter.default.addObserver( self, selector: #selector(handleWheelStop), name: .wheelDidStopRotating, object: nil ) } @objc private func handleWheelStop() { methodToCall() } deinit { // 记得移除观察者,避免内存泄漏 NotificationCenter.default.removeObserver(self) } }
方案选择建议
- 如果你只需要
Main控制器一个地方接收回调,优先选代理模式或闭包回调,代码更清晰,耦合度更低; - 如果有多个组件需要监听转轮停止事件,再考虑用通知中心。
内容的提问来源于stack exchange,提问作者aswiftnewbie27
相关产品推荐
相关产品推荐

