Swift 在特殊情况下,不需要使用脱硝剂,这涉及到不可清洗性
我遇到了一些奇特有趣的东西,我很想从任何人那里得到信息。因此,首先让我们对类进行以下定义:Swift 在特殊情况下,不需要使用脱硝剂,这涉及到不可清洗性,swift,automatic-ref-counting,weak-references,deinit,Swift,Automatic Ref Counting,Weak References,Deinit,我遇到了一些奇特有趣的东西,我很想从任何人那里得到信息。因此,首先让我们对类进行以下定义: class TestClass:NSObject { var s1 = NSHashTable<TestClass>(options: .weakMemory) func doit(bla:TestClass) { s1.add(bla) bla.s1.add(self) } deinit {
class TestClass:NSObject {
var s1 = NSHashTable<TestClass>(options: .weakMemory)
func doit(bla:TestClass) {
s1.add(bla)
bla.s1.add(self)
}
deinit {
print("Deinit")
}
}
如果我们执行以下操作,Denit将被调用:
t1?.s1.add(t2!)
t2?.s1.add(t1!)
t1 = nil // This will result in deinit being called
现在让我们通过调用doit()方法来做同样的事情
这里的问题是为什么在这种情况下不叫Denit?因为它本质上与第一个方法具有相同的引用赋值,所以它有什么不同
我很想从任何人那里得到关于这个的信息。
deinit
不会被调用,因为您已经创建了
首先,您要创建一个从self
到bla
的强大引用:s1。添加(bla)
其次,创建从bla
到self
的强引用:bla.s1.add(self)
现在它们都有相互的引用,所以如果你只是将其中一个置空,它们就不会被deinit
我修改了您的TestClass
以删除引用循环:
class TestClass:NSObject {
weak var s1 = NSHashTable<TestClass>(options: .weakMemory)
func doit(bla:TestClass) {
s1?.add(bla)
bla.s1?.add(self)
}
deinit {
print("Deinit")
}
}
类TestClass:NSObject{
弱变量s1=NSHashTable(选项:。弱内存)
func doit(bla:TestClass){
s1?添加(bla)
bla.s1?添加(自身)
}
脱硝{
印刷品(“脱硝”)
}
}
现在,您的第二次呼叫将正确触发Denit。与往常一样,问题是您正试图在操场上测试此功能。不要。操场是魔鬼的杰作 在实际的应用程序项目中进行测试,您将看到调用了
deinit
示例(iOS,但macOS中的等效版本也可以):
导入UIKit
类TestClass:NSObject{
变量s1=NSHashTable(选项:.weakMemory)
func doit(bla:TestClass){
s1.添加(bla)
bla.s1.添加(自身)
}
脱硝{
印刷品(“脱硝”)
}
}
类ViewController:UIViewController{
变量t1:TestClass?=TestClass()
变量t2:TestClass?=TestClass()
重写func viewDidLoad(){
super.viewDidLoad()
t1?.doit(bla:t2!)
t1=nil/-->“脱硝”
打印(t2?.s1)/-->它是空的
}
}
您是如何测试代码的?行t1?.doit(t2!)
未在Swift 3中编译。就我测试而言,两个代码(t1?.doit(t2!)
固定为t1?.doit(bla:t2!)
)在t1=nil行显示了Deinit
。(Xcode 8.2.1,命令行工具项目)我无法在Swift 3.0.2或Swift 3.1.1中复制此内容code@OOPer我在操场上运行了doit()
方法调用(相同的xcode版本),而Deinit
根本没有打印出来。它只使用第一种方法打印。没有引用循环,因为NSHashTable
包含对添加对象的弱引用。您可以自己测试:t1?.doit(t2!)print(“t1=\(t1!)”)t1=nil print(t2!.s1.allObjects)//在这里您将看到t1地址
no,正如我所期望的那样,我刚刚打印了[]
,当选项提供了weakMemory
时,哈希表包含对添加对象的弱引用:
(请随意)。我看到了选项,但对我来说,即使我对@Hamish执行了t1=nil
,它仍然存在,这就是将s1设置为.weakMemory
的要点,以便所持有的引用是弱关系。因为它们被弱持有t1=nil
应该能够被释放
t1?.doit(bla:t2!)
t1 = nil // Deinit doesn't get called for some reason
class TestClass:NSObject {
weak var s1 = NSHashTable<TestClass>(options: .weakMemory)
func doit(bla:TestClass) {
s1?.add(bla)
bla.s1?.add(self)
}
deinit {
print("Deinit")
}
}
import UIKit
class TestClass:NSObject {
var s1 = NSHashTable<TestClass>(options: .weakMemory)
func doit(bla:TestClass) {
s1.add(bla)
bla.s1.add(self)
}
deinit {
print("Deinit")
}
}
class ViewController: UIViewController {
var t1:TestClass? = TestClass()
var t2:TestClass? = TestClass()
override func viewDidLoad() {
super.viewDidLoad()
t1?.doit(bla:t2!)
t1 = nil // --> "Deinit"
print(t2?.s1) // --> it's empty
}
}