gpt4 book ai didi

swift - 这是强引用循环还是内存泄漏?

转载 作者:搜寻专家 更新时间:2023-11-01 07:23:41 26 4
gpt4 key购买 nike

我经常看到的关于强引用循环的例子涉及两个属性相互指向的类。但是,如果只有一个类具有指向另一个实例的属性,如下所示:

class ClassA {
var classB: ClassB? = nil
}

class ClassB {

}

然后我这样创建我的实例:

var myClassA = ClassA()
var myClassB = ClassB() //Reference count 1
myClassA.classB = myClassB //Reference count 2

// Now deallocate
myClassB = nil //Reference count 1
myClassA = nil

因为我释放了 myClassB,所以引用计数为 1。myClassA.classB 的引用计数发生了什么变化?它从未达到零,因为我从未执行过 myClassA.classB = nil 或使用 deinit 来执行此操作。自从我执行 myClassA = nil 以来,这是隐式完成的吗?

这是否可以归类为强引用循环?我想这至少是内存泄漏,这是真的吗?

最佳答案

正如@ozgur、@jtbandes、@Avi 和@Rob 在评论中解释的那样,不存在强引用循环或泄漏。

这是一个基于@Rob 的评论的示例,您可以在 Playground 中运行:

class ClassA {
var classB: ClassB?

deinit {
print("ClassA deallocated")
}
}

class ClassB {
deinit {
print("ClassB deallocated")
}
}

class Tester {
func test() {
var myClassA: ClassA! = ClassA()
var myClassB: ClassB! = ClassB() //Reference count 1
myClassA.classB = myClassB //Reference count 2

// Now deallocate
print("setting myClassB to nil")
myClassB = nil //Reference count 1
print("setting myClassA to nil")
myClassA = nil
print("all done")
}
}

// Create `Tester` object and call `test`:

Tester().test()

输出:

setting myClassB to nil
setting myClassA to nil
ClassA deallocated
ClassB deallocated
all done

需要注意的是,即使您先将 myClassB 设置为 nilmyClassA 也会先被释放。当 myClassA 被释放时,对 myClassB 的最终引用由 ARC 释放,然后 myClassB 被释放。


为了演示强引用循环,让 ClassB 保留对 ClassA 的强引用:

class ClassA {
var classB: ClassB?

deinit {
print("ClassA deallocated")
}
}

class ClassB {
var classA: ClassA?

deinit {
print("ClassB deallocated")
}
}

class Tester {
func test() {
var myClassA:ClassA! = ClassA()
var myClassB:ClassB! = ClassB() //Reference count 1
myClassA.classB = myClassB //Reference count 2
myClassB.classA = myClassA

// Now deallocate
print("setting myClassB to nil")
myClassB = nil //Reference count 1
print("setting myClassA to nil")
myClassA = nil
print("all done")
}
}

Tester().test()

输出:

setting myClassB to nil
setting myClassA to nil
all done

如果这两个对象都包含对另一个的强引用,那么这两个对象都不会被释放。要打破这种强引用循环,请将 classBclassA 属性之一声明为 weak。您选择哪一个会影响对象被释放的顺序:

如果在 ClassA 中声明 weak var classB: ClassB:

输出:

setting myClassB to nil
ClassB deallocated
setting myClassA to nil
ClassA deallocated
all done

相反,如果您声明 weak var classA: ClassA in ClassB:

输出:

setting myClassB to nil
setting myClassA to nil
ClassA deallocated
ClassB deallocated
all done

关于swift - 这是强引用循环还是内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37371225/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com