Swift deinit方法中使用self是否为最佳实践?与Objective-C是否一致?
在Swift的deinit中使用self是否属于最佳实践?
这个问题特别戳中从Objective-C转Swift开发者的痛点——毕竟老习惯改起来总需要理清楚背后的逻辑,咱们一步步说:
先聊Objective-C里为什么要避免在init/dealloc用self
在Objective-C中,大家会刻意避开在init和dealloc里用self,核心原因有两个:
init阶段:对象还没完全初始化完成,如果通过self调用实例方法,万一子类重写了这个方法,子类的实现可能会访问还没初始化的属性,直接引发崩溃;dealloc阶段:对象已经进入销毁流程,isa指针可能被runtime修改,或者一些关联对象已经被释放,此时用self调用方法或访问属性,很容易触发野指针或者意外的行为。
那Swift的deinit里用self到底行不行?
答案是:完全可以,而且很多场景下是必须的最佳实践。
Swift的deinit和Objective-C的dealloc底层逻辑差异很大:
- Swift的ARC在编译期就做了严格的生命周期管理,
deinit被调用时,对象的所有存储属性都还处于可用状态,直到deinit执行完毕,才会开始逐个释放属性; - Swift没有Objective-C那种runtime层面的isa指针动态修改(除非你刻意用ObjC runtime API,但那属于特殊场景),
self在deinit里的指向是完全确定的。
日常开发中,我们在deinit里做的清理工作几乎都离不开self:
class NotificationSubscriber { init() { NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: .someNotification, object: nil) } @objc private func handleNotification() {} deinit { // 必须用self移除观察者 NotificationCenter.default.removeObserver(self) } }
再比如取消网络请求、移除KVO观察者、关闭文件句柄这些操作,都需要通过self来访问属性或调用方法,这都是标准的安全写法。
那Swift的init里用self需要注意什么?
顺带提一句,Swift的init确实有约束,但和Objective-C的原因不一样:
Swift要求必须先初始化所有存储属性,才能使用self——这是Swift的安全机制,确保你不会访问未初始化的内存。一旦所有属性都初始化完成,在init里用self调用方法、访问属性都是安全的,不像Objective-C那样有子类重写的隐患(Swift里如果父类的方法是final的,子类根本没法重写;如果是可重写的,你也可以通过super来调用父类实现,避免意外)。
总结
- Objective-C中
init/dealloc避免用self的原则,完全不适用于Swift的deinit; - Swift的
deinit中使用self不仅安全,还是完成资源清理工作的必要手段,属于最佳实践; - Swift的
init里用self只要遵守“先初始化所有属性”的规则,就没有问题。
内容的提问来源于stack exchange,提问作者srus2017
相关产品推荐
相关产品推荐

