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

两处给Swift单例GameCenterFacade设置delegate仅一处生效,如何实现多对象接收回调?

问题解答

单例与代理的关系说明

  • 标准代理(Delegate)模式的默认设计就是单接收对象,和是否为单例没有关联。你遇到的覆盖问题是因为常规的delegate属性只声明为单个弱引用对象,后赋值的实例会直接覆盖之前的赋值,所以才会只有最后设置的自定义类能收到回调。

多对象同时接收回调的可行方案

方案1:改造单例实现多播代理(最规范)

修改GameCenterFacade的内部逻辑,将单个delegate替换为弱引用的代理集合,避免循环持有问题,建议使用NSPointerArray实现:

// GameCenterFacade 内部代码
private var delegates = NSPointerArray.weakObjects()

// 新增添加代理的公开方法
func addDelegate(_ delegate: GameCenterDelegate) {
    delegates.addObject(delegate)
}

// 触发回调时遍历所有代理执行
private func triggerCallback() {
    delegates.allObjects.forEach { object in
        guard let delegate = object as? GameCenterDelegate else { return }
        // 调用对应的协议方法即可
        delegate.gameCenterDidReceiveData?()
    }
}

改造完成后,两边都不再执行GameCenterFacade.shared.delegate = self的赋值,统一调用GameCenterFacade.shared.addDelegate(self)即可同时收到回调。

方案2:用通知中心中转回调(改造成本最低)

如果不想改动GameCenterFacade的原有实现,可以用通知做中转:

  1. 保留其中一个对象作为唯一delegate(比如自定义类),该对象收到回调时发送全局通知
  2. ViewController监听对应通知执行自身逻辑即可
// 自定义类收到代理回调时
func gameCenterDidReceiveData() {
    // 自身逻辑处理完成后发通知
    NotificationCenter.default.post(name: NSNotification.Name("GameCenterDidReceiveData"), object: nil)
}

// ViewController viewDidLoad 中添加监听
NotificationCenter.default.addObserver(self, selector: #selector(handleGameCenterData), name: NSNotification.Name("GameCenterDidReceiveData"), object: nil)

方案3:中间代理转发

你可以创建一个独立的中间代理类,作为GameCenterFacade唯一的delegate,内部持有ViewController和自定义类的弱引用,收到回调后分别转发给两个对象即可。

内容的提问来源于stack exchange,提问作者Charlie S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:06:03