You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4.0跨类调用方法:如何在WheelDelegate触发Main控制器方法

解决转轮停止后调用视图控制器方法的问题

我来帮你搞定这个问题——要在转轮的角速度降为0时,调用Main视图控制器里的methodToCall方法,核心是建立WheelDelegate和Main之间的通信关联。下面给你三种iOS开发中常用的实现方案,你可以根据自己的项目架构选择最合适的:

方案一:代理模式(推荐,耦合度低且易维护)

代理模式是组件间通信的经典方式,适合这种一对一的回调场景:

  1. 首先定义一个代理协议,用来声明转轮停止的回调方法:
protocol WheelStopDelegate: AnyObject {
    func wheelDidStopRotating()
}
  1. 修改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()
            }
        }
    }
}
  1. 让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()
    }
}

方案二:闭包回调(简洁灵活)

闭包是更轻量化的回调方式,代码更紧凑:

  1. 在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?()
            }
        }
    }
}
  1. 在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
    }
}

方案三:通知中心(适合跨多个组件的场景)

如果你的项目中需要多个地方监听转轮停止事件,可以用通知中心:

  1. 先定义一个自定义通知名称:
extension Notification.Name {
    static let wheelDidStopRotating = Notification.Name("WheelDidStopRotating")
}
  1. 在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)
            }
        }
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:46:51