为了账号安全,请及时绑定邮箱和手机立即绑定

在SWIFT中,我们是否应该始终使用[自己不拥有的]内部封闭

在SWIFT中,我们是否应该始终使用[自己不拥有的]内部封闭

鸿蒙传说 2019-06-24 13:41:34
在SWIFT中,我们是否应该始终使用[自己不拥有的]内部封闭在WWDC 2014会议上403中间SWIFT和成绩单,有下面的幻灯片演讲者说,如果我们不用[unowned self]在那里,这将是一个内存泄漏。这是否意味着我们应该一直使用[unowned self]内部关闭?在……上面ViewController.Swift天气应用程序的第64行,我不使用[unowned self]..但是我使用一些@IBOutlet就像self.temperature和self.loadingIndicator..可能没问题,因为@IBOutlets我定义的是weak..但是为了安全,我们是不是应该一直用[unowned self]?class TempNotifier {   var onChange: (Int) -> Void = {_ in }   var currentTemp = 72   init() {     onChange = { [unowned self] temp in       self.currentTemp = temp    }   }}
查看完整描述

3 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

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

示例:发出异步网络请求

如果您正在发出异步网络请求,则希望保留闭包self当请求完成时。否则,该对象可能已被解除分配,但您仍然希望能够处理请求完成。

何时使用unowned selfweak self

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

在闭包的特定情况下,您只需要意识到在其中引用的任何变量都会被闭包“拥有”。只要闭包在附近,这些对象就一定会出现。阻止这种所有权的唯一方法是[unowned self][weak self]..因此,如果一个类拥有一个闭包,并且该闭包捕获了对该类的强引用,那么在闭包和类之间有一个很强的引用周期。这还包括类是否拥有闭包的东西。

特别是在视频的例子中

在幻灯片的例子中,TempNotifier通过onChange成员变量如果他们不宣布selfunowned,关闭也将拥有self创建一个强大的参考周期。

差异unownedweak

.之间的区别unownedweak那是weak声明为可选时间。unowned不是。宣布weak你需要处理的情况是,它可能是零内关闭在某个时间点。如果您试图访问unowned变量碰巧为零,它将使整个程序崩溃。所以只能用unowned当您是正数时,当闭包出现时,该变量将始终存在。


查看完整回答
反对 回复 2019-06-24
?
交互式爱情

TA贡献1712条经验 获得超3个赞

我想我应该为视图控制器添加一些具体的例子。许多解释,不仅仅是Stack溢出的解释,真的很好,但我更好地处理了现实世界的例子(@drewag在这方面有了一个良好的开端):

  • 如果您有一个闭包来处理来自网络请求的响应,请使用

    weak

    因为他们活得很久。视图控制器可以在请求完成之前关闭

    self

    在调用闭包时不再指向有效对象。
  • 如果有处理按钮上的事件的闭包。这可能是unowned因为一旦视图控制器消失,按钮和它可能引用的任何其他项就会从self同时离开。封闭区也会同时消失。

    class MyViewController: UIViewController {
          @IBOutlet weak var myButton: UIButton!
          let networkManager = NetworkManager()
          let buttonPressClosure: () -> Void // closure must be held in this class. 
    
          override func viewDidLoad() {
              // use unowned here          buttonPressClosure = { [unowned self] in
                  self.changeDisplayViewMode() // won't happen after vc closes. 
              }
              // use weak here          networkManager.fetch(query: query) { [weak self] (results, error) in
                  self?.updateUI() // could be called any time after vc closes          }
          }
          @IBAction func buttonPress(self: Any) {
             buttonPressClosure()
          }
    
          // rest of class below. }


查看完整回答
反对 回复 2019-06-24
  • 3 回答
  • 0 关注
  • 631 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信