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

遵循协议的类扩展中如何避免重写get/set并使用默认实现

问题解决:协议扩展中属性默认实现的无限递归问题

错误原因

你写的计算属性会触发无限递归:

  • get方法里返回self.didSelectSpecificCoinClousre,会再次调用该属性的get方法,循环往复
  • set方法里给self.didSelectSpecificCoinClousre赋值,又会触发set方法,形成死循环

所以编译器抛出了“Function call causes an infinite recursion”警告。

解决方案

Swift协议扩展无法直接添加存储属性,要实现{ get set }属性的默认实现,有两种可行方式:

方式1:用关联对象实现(适用于继承NSObject的类)

借助Objective-C运行时的关联对象,给协议扩展模拟存储属性:

首先修改协议,添加@objc标记并继承NSObjectProtocol:

@objc protocol SelectedSpecificCoinProtocol: NSObjectProtocol {
    typealias didSelectHandler = () -> Void?
    var didSelectSpecificCoinClousre: didSelectHandler? { get set }
}

然后在协议扩展中实现属性的get/set:

// 定义唯一关联键
private var didSelectKey = 0

extension SelectedSpecificCoinProtocol where Self: NSObject {
    var didSelectSpecificCoinClousre: didSelectHandler? {
        get {
            return objc_getAssociatedObject(self, &didSelectKey) as? didSelectHandler
        }
        set {
            objc_setAssociatedObject(self, &didSelectKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

这样,只要你的类继承NSObject并遵循该协议,就自动获得属性的默认实现,无需手动重写。

方式2:让遵循协议的类自行定义存储属性

如果不想依赖Objective-C运行时,最简单的方式是让每个遵循协议的类直接定义存储属性:

protocol SelectedSpecificCoinProtocol {
    typealias didSelectHandler = () -> Void?
    var didSelectSpecificCoinClousre: didSelectHandler? { get set }
}

// 示例类
class CoinSelector: SelectedSpecificCoinProtocol {
    // 直接定义存储属性,自动满足协议要求
    var didSelectSpecificCoinClousre: didSelectHandler?
}

这种方式无需额外代码,只是每个遵循协议的类都要自己声明这个属性。

小提示

你的类型别名() -> (Void)?可以简化为() -> Void?,语法更简洁,功能完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 17:15:49