Swift中父子类弱引用及全弱引用影响与默认强引用原因
问题1:Swift中父类和子类实例互相使用weak引用会发生什么?
首先明确场景:这里指父类实例与子类实例互相持有对方的weak引用(子类继承自父类,但二者是独立的实例对象)。
weak引用的核心特性是:不会增加对象的引用计数,当对象没有任何强引用时会被立即销毁,同时weak引用会自动置为nil。
代码示例
class ParentClass { weak var child: ChildClass? deinit { print("ParentClass deinit") } } class ChildClass: ParentClass { weak var parent: ParentClass? deinit { print("ChildClass deinit") } } func testWeakReferences() { let parent = ParentClass() let child = ChildClass() parent.child = child child.parent = parent // 函数执行完毕后,parent和child的局部强引用会被销毁 } testWeakReferences()
运行结果
ChildClass deinit ParentClass deinit
原因说明
- 当
testWeakReferences函数执行结束,局部变量parent和child的强引用被销毁,此时两个实例没有任何剩余的强引用。 - 互相的
weak引用不会阻止对象释放,也不会形成循环引用(循环引用需要至少一方是强引用),因此两个实例会被立即销毁,各自的deinit方法执行。
如果是子类继承父类后,重写父类的weak属性仍保持weak,这属于常规的weak属性继承,不会产生特殊问题,本质还是遵循weak引用的常规行为。
问题2:全部使用weak引用的影响,以及Swift默认用强引用的原因
全部使用weak引用的致命问题
weak引用的存在依赖于其他强引用持有对象,否则对象会被立即销毁。如果所有变量都声明为weak,绝大多数对象将无法存活,根本无法完成正常的业务逻辑。
反例1:单个对象的情况
class User { var name: String init(name: String) { self.name = name } deinit { print("User \(name) deinit") } } func testAllWeak() { weak var user: User? = User(name: "Akshay") // 刚创建的User实例没有任何强引用,会被立即销毁 print(user?.name ?? "nil") // 输出nil } testAllWeak()
运行结果
User Akshay deinit nil
反例2:集合存储对象的情况
func testWeakArray() { weak var users: [User]? = [User(name: "A"), User(name: "B")] // 数组本身是weak引用,且数组内的对象无强引用,会被立即销毁 print(users?.count ?? 0) // 输出0 } testWeakArray()
可以看到,全部使用weak会导致对象无法被正常持有和使用,完全违背开发的基本需求。
为什么Swift默认使用强引用
强引用的核心作用是维持对象的生命周期,默认使用强引用是权衡后的合理设计,原因有两点:
- 符合直觉的生命周期管理:绝大多数场景下,我们创建对象是为了使用它,希望它在主动放弃前一直存在。强引用的逻辑是“我持有这个对象,它就不会消失”,完全符合开发者的直觉。
- 避免不必要的复杂性:如果默认是
weak,开发者必须手动为每个对象创建强引用来维持存活,这会增加大量冗余代码,还极易因忘记添加强引用导致对象意外销毁,引发难以排查的bug。
循环引用是强引用在特定场景(如双向引用)下的问题,但可以通过weak或unowned针对性解决。Swift将强引用设为默认,是因为它覆盖了绝大多数开发场景的需求,把特殊场景的解决方案交给开发者手动处理,兼顾了易用性和灵活性。
内容的提问来源于stack exchange,提问作者Akshay Pure
相关产品推荐
相关产品推荐

