我们应该总是在 Swift 的闭包中使用 [unowned self] [英] Shall we always use [unowned self] inside closure in Swift

查看:37
本文介绍了我们应该总是在 Swift 的闭包中使用 [unowned self]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 WWDC 2014 session 403 ,我不使用[unowned self].但是我通过使用一些 @IBOutlet 来更新 UI,比如 self.temperatureself.loadingIndicator.可能没问题,因为我定义的所有 @IBOutlet 都是 weak.但是为了安全起见,我们应该总是使用 [unowned self] 吗?

class TempNotifier {var onChange: (Int) ->void = {_ in }var currentTemp = 72在里面() {onChange = { [unowned self] temp inself.currentTemp = 温度}}}

解决方案

不,在某些时候您肯定不想使用 [unowned self].有时您希望闭包捕获 self 以确保在调用闭包时它仍然存在.

示例:发出异步网络请求

如果您正在发出异步网络请求,您确实希望闭包在请求完成时保留self.该对象可能已被释放,但您仍然希望能够处理请求完成.

何时使用unowned selfweak self

您真正想要使用 [unowned self][weak self] 的唯一时间是您创建一个 强参考周期.强引用循环是指当存在一个所有权循环时,对象最终相互拥有(可能通过第三方),因此它们永远不会被释放,因为它们都确保彼此保持存在.

在闭包的特定情况下,您只需要意识到在它内部引用的任何变量都由闭包拥有".只要闭包在附近,这些对象就可以保证在附近.停止这种所有权的唯一方法是执行[unowned self][weak self].因此,如果一个类拥有一个闭包,并且该闭包捕获了对该类的强引用,那么在该闭包和该类之间就有了一个强引用循环.这也包括类是否拥有拥有闭包的东西.

特别是视频中的例子

在幻灯片的示例中,TempNotifier 通过 onChange 成员变量拥有闭包.如果他们没有将 self 声明为 unowned,闭包也会拥有 self,从而创建一个强引用循环.

unownedweak 的区别

unownedweak 的区别在于 weak 被声明为 Optional 而 unowned 不是.通过将它声明为 weak,您可以处理在某些时候它在闭包内可能为零的情况.如果您尝试访问一个恰好为零的 unowned 变量,它将导致整个程序崩溃.因此,仅当您确定变量将始终存在而闭包存在时才使用 unowned

In WWDC 2014 session 403 Intermediate Swift and transcript, there was the following slide

The speaker said in that case, if we don't use [unowned self] there, it will be a memory leak. Does it mean we should always use [unowned self] inside closure?

On line 64 of ViewController.swift of the Swift Weather app, I don't use [unowned self]. But I update the UI by using some @IBOutlets like self.temperature and self.loadingIndicator. It may be OK because all @IBOutlets I defined are weak. But for safety, should we always use [unowned self]?

class TempNotifier {
  var onChange: (Int) -> Void = {_ in }
  var currentTemp = 72
  init() {
    onChange = { [unowned self] temp in
      self.currentTemp = temp
    }
  }
}

解决方案

No, there are definitely times where you would not want to use [unowned self]. Sometimes you want the closure to capture self in order to make sure that it is still around by the time the closure is called.

Example: Making an asynchronous network request

If you are making an asynchronous network request you do want the closure to retain self for when the request finishes. That object may have otherwise been deallocated but you still want to be able to handle the request finishing.

When to use unowned self or weak self

The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.

In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self] or [weak self]. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.

Specifically in the example from the video

In the example on the slide, TempNotifier owns the closure through the onChange member variable. If they did not declare self as unowned, the closure would also own self creating a strong reference cycle.

Difference between unowned and weak

The difference between unowned and weak is that weak is declared as an Optional while unowned is not. By declaring it weak you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned variable that happens to be nil, it will crash the whole program. So only use unowned when you are positive that variable will always be around while the closure is around

这篇关于我们应该总是在 Swift 的闭包中使用 [unowned self]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆