我经常看到的关于强引用循环的示例涉及两个具有指向彼此的属性的类。但是,如果只有一个类具有指向另一个实例的属性,如下所示:
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
完成后隐式完成的吗?
这可以归类为强参考周期吗?我会想象它至少是一个内存泄漏,这是真的吗?
答案 0 :(得分:2)
正如@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
设置为nil
,也会先释放myClassA
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
输出:
classB
如果对象都包含对另一个的强引用,则它们都不会被释放。要打破此强引用周期,请将classA
或weak
属性之一声明为weak var classB: ClassB
。您选择哪一个会影响对象被释放的顺序:
如果您在ClassA
中声明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
:
输出:
struct ImageFrame { Image image; }; struct Image { ImageFrame imageFrame; };