每当我进行异步网络请求时,可能是在请求到达时self已经是nil(例如,ViewController已被解除)。
为了防止这种情况,我通常将自我视为弱者:
future.onSuccess(context: Queue.main.context, callback: { [weak self] result in
if let strongSelf = self {
// Do some stuff with self, which is now guaranteed to be not nil
// strongSelf.someMethod()
}
})
或者我可以把自己视为无主的:
future.onSuccess(context: Queue.main.context, callback: { [unowned self] result in
// Do some stuff with self
// self.someMethod()
})
我不关心请求返回,因为当请求在ViewController已被解除的时间点返回时,我没有从请求中显示任何内容。所以我不想让自己保持活力#34;关闭。
我现在的问题是 - 在这种情况下是否足以将自己视为无主?或者我必须一直做[零自我]的零检查?如果在请求到达并且self已经为零时无主捕获的情况下会发生什么 - 闭包是否仍然存在且将执行并且将在访问nil时触发运行时错误?或者关闭也会与自我一起解除分配,并且请求会遇到" void"?
或者在这种情况下我可以忘记弱者和无人物,因为当自我解除分配时,关闭也将被解除分配,因此在请求到达时没有访问nil的危险吗?
PS:我知道关于这个主题已经有很多问题 - 答案,但在我不关心异步到达的情况下我找不到答案。
答案 0 :(得分:8)
如果您在没有weak
或unowned
关键字的情况下捕获self,则视图控制器将由闭包保留,并且在闭包死亡之前不会解除分配。 weak
和unowned
之间的区别在于weak
是可选的,需要条件绑定作为安全检查。另一方面,unowned
不是故障安全的。它假定您的视图控制器仍处于活动状态,如果不存在则会崩溃。有关详细信息,请参阅this answer。
答案 1 :(得分:5)
在这种情况下,您不希望使用unowned
,因为如果在调用完成之前取消分配对象,则您有一个未设置为nil
的悬空引用。如果您在请求完成时尝试使用此引用,则应用程序将崩溃。
顺便说一句,如果您真的不再需要响应,则还应在取消分配视图控制器时取消该请求。如果您使用NSURLSession
,则始终会获得可以取消的NSURLSessionTask
引用。因此,通常会将闭包中[weak self]
模式的使用与保存对NSURSessionTask
的额外弱引用的代码结合起来,并使deinit
有条件地取消该模式。