【问题标题】:Capturing self weak or unowned on asynchronous network requests在异步网络请求上捕获自身弱或无主
【发布时间】:2016-01-27 03:32:15
【问题描述】:

每当我进行异步网络请求时,可能在请求到达时 self 已经为零(例如 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 已被解除的时间点返回时,我没有任何可显示的请求。所以我不想让自己在闭包中“活着”。

我现在的问题是 - 在这种情况下是否足以将自己捕获为无主?还是我必须一直对 [weak self] 进行 nil 检查?如果在请求到达并且 self 已经为零时使用请求进行无主捕获会发生什么 - 闭包是否仍然存在并且会执行并且会在访问 nil 时触发运行时错误?或者闭包是否也会与 self 一起被释放,并且请求会进入“void”?

或者我可以在这种情况下忘记弱和无主,因为当 self get 被释放时,闭包也将被释放,因此在请求到达时没有访问 nil 的危险?

PS:我知道关于这个主题已经有很多问题-答案,但是在我不关心异步到达的情况下我找不到答案。

【问题讨论】:

  • 如果我们假设future 的生命周期独立于self 使用的任何东西,那么使用unowned 将是不安全的,因为self 可能是deallocedfuture 和它的参考关闭继续存在。

标签: swift asynchronous closures


【解决方案1】:

如果您在没有weakunowned 关键字的情况下捕获self,您的视图控制器将被闭包保留,并且不会在闭包死亡之前解除分配。 weakunowned 之间的区别在于 weak 是 Optional 并且需要条件绑定作为安全检查。另一方面,unowned 不是故障安全的。它假定您的视图控制器还活着,如果不是,它将崩溃。如需更多信息,请参阅this answer

【讨论】:

  • 是的,我会在大多数情况下使用它。
  • 当我不使用 weak 或 unowned 时:我不明白当 self 被释放时是什么让闭包保持“活动”。谁或什么使关闭保持活力?任何地方都没有提到它。
  • 例如,如果您使用NSURLSession,会话本身会管理引用。闭包中的内容无关紧要,也不会影响其生命周期。
  • 啊,所以闭包的调用者是使闭包保持活动状态的实例?
  • 谢谢,回答了我的问题!
【解决方案2】:

在这种情况下您不想使用unowned,因为如果对象在调用完成之前被释放,那么您有一个未设置为nil 的悬空引用。如果您在请求完成时尝试使用此引用,应用程序将崩溃。

顺便说一句,如果您真的不再需要响应,您还应该在视图控制器被释放时取消请求。如果您使用NSURLSession,您总是会得到一个可以取消的NSURLSessionTask 引用。因此,人们通常会将闭包中[weak self] 模式的使用与保存对NSURSessionTask 的额外弱引用的代码结合起来,并有一个deinit 有条件地取消它。

【讨论】:

  • 感谢您提出取消请求的想法。我正在使用 AFNetworking,但从未考虑过这一点。
  • 如果您正在使用AFHTTPSessionManager(并且您不应该再使用AFHTTPRequestOperationManager),您将获得NSURLSessionTask 引用,您可以将其保存为可选并稍后取消。
猜你喜欢
  • 2020-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
相关资源
最近更新 更多