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

声明static代理可行但weak代理无效的技术问题排查

Weak代理无法生效的问题排查与解决

我用代理模式在视图控制器间传递消息时遇到问题:声明weak代理无法触发回调,但改用static代理可以正常工作。相关代码如下:

发送消息的视图控制器

protocol SendMessageDelegate: AnyObject {
    func message(text: String)
}

final class SendMessageController: UIViewController {
    weak var delegate: SendMessageDelegate?

    @objc func button() {
        sendMessage()
    }

    func sendMessage() {
       let message = "Hello World" // 注:原代码使用了中文引号,需替换为英文引号
       delegate?.message(text: message)
    }
}

接收消息的视图控制器

final class ShowMessageController: UIViewController, SendMessageDelegate {
     
    let sendMessageController = SendMessageController() 
     
    override func viewDidLoad() {
        sendMessageController.delegate = self
    }
    
    func message(text: String) {
        print("The message is:\(text)")
    }       
}

问题原因

核心问题出在ShowMessageController中sendMessageController实例的生命周期:
你在ShowMessageController里用let声明了一个局部实例,但这个实例没有被添加到视图层级,也没有其他强引用持有它。viewDidLoad执行完毕后,这个实例会被立即释放,导致weak修饰的delegate也随之失效,后续调用delegate?.message自然不会触发回调。

而static代理之所以能工作,是因为static变量属于全局强引用,实例不会被释放,但这种写法会带来内存泄漏风险,不建议使用。

解决方法

1. 正确持有并展示SendMessageController实例

如果是通过模态或push方式展示SendMessageController,不要在ShowMessageController里创建局部实例,而是在跳转时初始化并设置代理:

final class ShowMessageController: UIViewController, SendMessageDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // 示例:点击按钮触发跳转
    @objc func presentSendVC() {
        let sendVC = SendMessageController()
        sendVC.delegate = self
        present(sendVC, animated: true)
    }

    func message(text: String) {
        print("The message is:\(text)")
    }
}

此时sendVC会被UIKit的视图层级强引用,不会提前释放,weak代理就能正常接收消息。

2. 验证实例生命周期

可以在SendMessageController中添加deinit方法,检查实例是否被提前释放:

final class SendMessageController: UIViewController {
    weak var delegate: SendMessageDelegate?

    deinit {
        print("SendMessageController 已销毁")
    }

    // 其他代码...
}

如果在调用sendMessage之前就打印了销毁日志,说明实例被提前释放,需要重新梳理持有逻辑。

3. 修正语法错误

原代码中的字符串使用了中文引号“Hello World”,需替换为英文引号"Hello World",否则会导致编译失败。


内容的提问来源于stack exchange,提问作者Toshiro Vernon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:57:51