1

(我了解 ARC 的工作原理以及 和 之间的区别weakunowned问题是关于它们的特定用途以及为什么它不起作用。unowned为了简单起见,我将在下面的示例中使用。)

请参见下面的示例。注意第 10 行,它旨在将传递的强引用更改为无主​​引用。我认为这会起作用,但是当我最近在我的代码中使用它时,我发现我错了。

 1  import Foundation
   
 2  class MyClass {
 3      var uuid: UUID = UUID()
 4      
 5      deinit {
 6          print("Deinited!")
 7      }
 8  }
   
 9  func test(_ d: inout [UUID:MyClass], _ o: MyClass) {
10      unowned let u = o  // <- !
11      d[u.uuid] = u
12  }
   
13  var d = [UUID: MyClass]()
14  test(&d, MyClass())

在 Playground 中运行上述代码。结果显示没有调用 deinit,表明对对象的强引用保存在字典中。

我想知道为什么?weak和关键字是否unowned仅适用于属性?但是上面的代码不会产生编译器错误,而且 Swift确实提到它可以在变量声明中使用:

您可以通过在属性或变量声明之前放置 unowned 关键字来指示无主引用。

谁能分享一下你是怎么理解的?谢谢!

顺便说一句,我知道如何解决这个问题(例如,使用这样的包装器。我试图理解的是为什么上面的代码不起作用。

4

2 回答 2

2

分配 ( a = b) 时,您无法控制引用a的类型。您只能控制对象a引用的内容。

这里:

d[u.uuid] = u

代码不是说:

u.uuid与 key in关联的值d设置为 (unowned) 引用u

它在说:

u.uuid与 key in关联的值d是一个引用(不是说是什么类型),它引用了u正在引用的内容。

无主的事实u是相当无关紧要的。字典将始终存储对对象的强引用。这就是它们的设计方式。

Weak<T>wrapper的情况下,字典仍然会存储对 的强引用Weak<T>,但会存储对被包装对象Weak<T>的弱引用。T这就是它如何实现没有对T对象的强引用。

于 2021-04-04T03:20:18.330 回答
0

@Sweeper 的回答包含我将在下面给出的所有要点。但我会尽量让它们更明确一点:

  • 变量代表一个存储(内存中的一个位置)
  • 赋值操作改变存储中的值
  • weakunowned是存储的属性。它们不受赋值操作的影响。

因此unowned,我的示例代码中第 10 行中的关键字仅影响特定的存储位置(它在堆栈中),并且对全局字典使用的存储属性没有影响(正如 @Sweeper 指出的那样)。

于 2021-04-04T03:42:52.820 回答