Swift:可以在可选绑定期间释放弱引用吗?

Posted

技术标签:

【中文标题】Swift:可以在可选绑定期间释放弱引用吗?【英文标题】:Swift: Can weak reference be deallocated during optional binding? 【发布时间】:2020-11-26 16:11:10 【问题描述】:

让我们看看下面的例子

SomeLib.someAsyncFunction  [weak someVariable] in
   if let someVariableU = someVariable 
      // now someVariableU is unwrapped and strong reference created , we can use it as regular
   

我假设可选绑定有一个类似于(当然不完全是)这样的低级实现

if variable != nil 
   return variable!

所以,我的问题 - 弱引用引用的对象是否有可能在可选绑定期间被释放,我的意思是对该对象的最后一个强引用被“清除”。如果是这样,这种情况会发生什么?

如果“nil 检查通过”然后将被释放会发生什么,“强制展开”会发生什么(我使用括号是因为我知道它不完全是这样工作的)!

那么,有人能解释一下这种情况是否可能发生,而且会发生什么?

【问题讨论】:

看看发出的机器码,你应该看到retain调用someVariableU 【参考方案1】:

整个结构可以追溯到 Objective-C 时代,传统上被称为“弱-强之舞”。让我解释一下舞蹈的目的。

我们的总体目标是:避免保留周期和内存泄漏的危险。这就是为什么我们说weak somevariable

然而,在这样做之后,我们确实引入了somevariable 指向的对象可能被释放的危险。但是,我们通过说if let 连贯地处理这种危险。方法如下:

当我们在您的代码中输入 first 花括号时,对象可能已被释放。但这不是问题。 if let 表示如果对象已被释放,那么在这种情况下,我们将得到 nil,但我们什么也不做(我们从不输入 second 花括号)。

如果对象没有第一个花括号释放,然后if let成功,然后,正如Cristik所说,if let 创建了一个强引用,现在我们输入 second 大括号,保证对象将保持完整。

因此,我们得到连贯一致的行为。

SomeLib.someAsyncFunction  // someVariable might be deallocated...
   [weak someVariable] in // ...and that is the point of `weak`, to allow that
   if let someVariableU = someVariable  // find out whether someVariable was deallocated
      // if we get here, someVariable was _not_ deallocated...
      // and someVariableU is a strong reference and persists thru this block
   

【讨论】:

感谢您的回答!它解释了很多事情!所以,基本上要澄清 - 我想知道是否可以在 if/guard let 语句本身期间释放弱引用的对象。我的意思是如果让语句(内部实现)必须首先检查变量是否确实具有值(未释放),然后才打开它。我的意思是可以在这些步骤之间进行重新分配吗?或者它是由某种“原子”操作制成的,在一次操作中完成所有这些步骤? 是的,说if let 的那一刻是原子的。我了解您认为这是两个步骤:(1)这件事还在吗? (2) 如果是,请打开它。但这不是两个步骤,至少不是在 1 和 2 之间可能发生的某种意义上。 换句话说,如果if let 不是原子的,那么整个宇宙现在已经爆炸了。但事实并非如此。 :) 基本上你是在问 ARC weak 的魔力是如何在幕后工作的。答案是,只要对对象的弱引用没有被簿记系统手动清零,该对象就有一个额外的保留计数,正是这样if let 之类的东西才能正确运行。相反,当所有强引用都消失时,弱引用被手动清零并且额外的保留计数减少——对象消失。 实际上我猜它是这样工作的,直到 Swift 4。对象被保留,直到它的所有弱引用都被清零。由于 Swift 4 objs 不存储弱引用计数以及直接在 obj 中引用它们自己!所以,基本上 obj 是“活的”,直到所有指向它的弱引用都被手动清零。【参考方案2】:

不,在执行可选绑定块期间不会释放对象。

if let someVariableU = someVariable 创建一个强引用,因此只要该强引用存在,它指向的对象也会存在。

【讨论】:

以上是关于Swift:可以在可选绑定期间释放弱引用吗?的主要内容,如果未能解决你的问题,请参考以下文章

swift 弱化函数可帮助您将实例弱绑定到静态方法引用

弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导

Swift学习笔记-自动引用计数弱引用和无主引用

Swift学习笔记-自动引用计数弱引用和无主引用

任何不一致的铸造?在可选绑定期间进入 Swift 中的协议

可以在调用实例方法时释放 Objective-C 对象吗?