如何解决为什么通过使用局部变量弱化强引用不起作用?
(我了解 ARC 的工作原理以及 weak
和 unowned
之间的区别。问题是关于它们的具体用途以及为什么它不起作用。我将使用 {{1} } 在下面的例子中只是为了简单起见。)
请参见下面的示例。注意第 10 行,它旨在将传递的强引用更改为无主引用。我认为这会奏效,但最近在我的代码中使用它时,我发现我错了。
unowned
在 Playground 中运行上述代码。结果显示没有调用deinit,说明字典中保存了对该对象的强引用。
不知道为什么? 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())
和 weak
关键字是否仅适用于属性?但是上面的代码不会产生编译器错误,而且 Swift book 确实提到它可以用于变量声明:
您可以通过放置 unowned 关键字来指示无主引用 在属性或变量声明之前。
谁能分享一下你是怎么理解的?谢谢!
顺便说一句,我知道如何解决这个问题(例如,使用像 this 这样的包装器)。我试图理解的是为什么上面的代码不起作用。
解决方法
在赋值 (a = b
) 时,你无法控制 a
是什么类型的引用。您只能控制 a
引用的对象。
这里:
d[u.uuid] = u
代码不是说:
与该键相关联的值u.uuid
在d
被设置为(无主)参考u
。
它说:
与 u.uuid
中的键 d
关联的值是一个引用(不说明是什么类型),指的是 u
所指的内容。
u
是无主的这一事实是无关紧要的。字典将始终存储对对象的强引用。它们就是这样设计的。
在 Weak<T>
wrapper 的情况下,字典仍将存储对 Weak<T>
的强引用,但 Weak<T>
将存储对包装的 T
对象的弱引用。这就是它如何实现没有对 T
对象的强引用。
@Sweeper 的回答包含我将在下面给出的所有要点。但我会尽量让它们更明确一点:
- 变量代表一个存储(内存中的一个位置)
- 赋值操作改变了存储中的值
-
weak
和unowned
是存储的属性。它们不受赋值操作的影响。
因此,我的示例代码中第 10 行中的 unowned
关键字仅影响该特定存储位置(它在堆栈中),并且对全局字典使用的存储属性没有影响(正如 @Sweeper 指出的那样) .
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。