Swift委托声明差异解析:两类委托赋值写法的正误原因探究
嘿,我来帮你理清楚这两个问题——先拆解为什么第二种赋值写法行不通,再聊聊委托声明里的关键细节差异:
一、为什么直接赋值FriendsFunctions()给delegate是错误的?
核心原因全在你给delegate加的weak关键字上,先看这个属性的声明:
weak var delegate: FriendsDelegate? = nil
weak修饰的变量有两个关键特性:
- 它不会增加对象的引用计数,只是持有对象的一个“弱引用”——一旦对象没有任何强引用持有它,就会被自动销毁,
weak变量也会立刻变成nil。 - Swift编译器会直接阻止你把临时对象赋值给
weak变量,因为这完全没有意义:当你写friendsFunctionsDelegate.delegate = FriendsFunctions()时,这个新建的FriendsFunctions实例没有被任何强引用变量(比如正确写法里的let friendsFunctions)持有,赋值语句执行完的瞬间,这个实例的引用计数就降到0,会被立即销毁,delegate马上就变成nil,后续调用delegate?.orderPizza()根本不会执行任何代码。
而正确写法中:
let friendsFunctions = FriendsFunctions() // 强引用持有这个实例 friendsFunctionsDelegate.delegate = friendsFunctions
friendsFunctions作为强引用,会让FriendsFunctions实例的引用计数保持大于0,只要friendsFunctions没有被销毁,weak的delegate就能安全引用它,直到friendsFunctions被释放,delegate才会自动变为nil。
二、委托声明中的关键细节差异
你的代码里有两个委托声明的核心设定,这里和你聊聊它们的作用,以及写法不同会带来什么影响:
1. protocol FriendsDelegate: AnyObject——类专属协议约束
你给协议加上了AnyObject,这意味着只有类(class)才能遵守这个协议,结构体、枚举这些值类型都不能实现它。
- 为什么要加这个?因为你需要用
weak修饰delegate——weak只能用于类实例(引用类型),值类型没有引用计数的概念,根本没法用weak修饰。 - 如果去掉
AnyObject约束,你就不能给delegate加weak关键字了,此时如果用var delegate: FriendsDelegate?(强引用),就很容易产生循环引用:比如如果FriendsFunctions也持有FriendsFunctionsDelegate的强引用,两个对象就会互相“抓着不放”,永远不会被销毁,造成内存泄漏。
2. weak var delegate: FriendsDelegate?——弱引用委托的必要性
用weak修饰委托属性是Swift委托模式的标准写法,目的就是避免循环引用:
- 在委托模式里,通常是“委托发起者”(比如
FriendsFunctionsDelegate)持有“被委托者”(比如FriendsFunctions)的引用,如果被委托者也持有委托发起者的强引用,就会形成循环引用。 - 用
weak让委托发起者只持有弱引用,这样即使被委托者持有委托发起者的强引用,也不会形成循环——当没有其他强引用指向被委托者时,它会被正常销毁,delegate自动变成nil。 - 如果不用
weak而用强引用,就必须手动管理引用关系,稍有不慎就会出现内存泄漏问题。
内容的提问来源于stack exchange,提问作者user15675885
相关产品推荐
相关产品推荐

