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

Swift委托声明差异解析:两类委托赋值写法的正误原因探究

嘿,我来帮你理清楚这两个问题——先拆解为什么第二种赋值写法行不通,再聊聊委托声明里的关键细节差异:

一、为什么直接赋值FriendsFunctions()给delegate是错误的?

核心原因全在你给delegate加的weak关键字上,先看这个属性的声明:

weak var delegate: FriendsDelegate? = nil

weak修饰的变量有两个关键特性:

  1. 它不会增加对象的引用计数,只是持有对象的一个“弱引用”——一旦对象没有任何强引用持有它,就会被自动销毁,weak变量也会立刻变成nil。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:27:41