我正在研究 obj-c/swift arc 系统。打印 CFGetRetainCount 函数创建的实例保留计数的日志。
我期望这样的引用计数
let foo1 = NSObject() // foo1 retain count 1
let foo2 = foo1 // foo1 retain count 2
foo2 = nil // foo1 retains count 1
foo1 = nil // foo1 retain count 0. release
但实际上..
let foo1 = NSObject() // foo1 retain count 2
let foo2 = foo1 // foo1 retain count 3
foo2 = nil // foo1 retain count 2
foo1 = nil // foo1 retain count 1. release
并直接打印 NSObject() 的保留计数..
print(CFGetRetainCount(NSObject())) // retain count 1
基本上,NSObject() 有 1 个保留计数。并在保留计数达到 2 时释放对象。
我知道在与实例强链接时会增加保留计数。但是刚刚创建的实例有1个保留计数,当保留计数变为1而不是0时释放实例。这些现象的原因是什么?
最佳答案
TL;DR 您记录的方式会影响结果,您可能会在记录时获得临时所有权,因此将所有打印结果增加 1。
以下答案是一种简化,因为您真的不必担心 retainCount
中的实际值。
保留计数记录给定对象有多少引用(所有者)。
创建时,只有一个所有者,因此保留计数设置为 1。每次对象获得新所有者(retain
)时,保留计数都会增加 1。每次对象丢失和所有者(release
)保留计数减一。
请注意,retainCount
永远不会达到零。如果拥有者的数量为 1 并且您失去了拥有者,则对象将被释放,然后计数不会减少。
为了更好的测试,我创建了一个没有 ARC 编译的 Obj-C 类:
@implementation TestObject
- (instancetype)init {
TestObject *result = [super init];
NSLog(@"Retain count after creation: %@", @(self.retainCount));
return result;
}
- (instancetype)retain {
TestObject *result = [super retain];
NSLog(@"Retain count after retain: %@", @(self.retainCount));
return result;
}
- (oneway void)release {
NSLog(@"Retain count before release: %@", @(self.retainCount));
[super release];
}
- (void)dealloc {
NSLog(@"Retain count before dealloc: %@", @(self.retainCount));
[super dealloc];
}
@end
并在 Swift 中使用它代替 NSObject
:
var foo1: TestObject? = TestObject()
print("#")
print(CFGetRetainCount(foo1))
var foo2 = foo1
print("#")
print(CFGetRetainCount(foo1))
foo2 = nil
print("#")
print(CFGetRetainCount(foo1))
foo1 = nil
导致:
Retain count after creation: 1
#
Retain count after retain: 2
2
Retain count before release: 2
Retain count after retain: 2
#
Retain count after retain: 3
3
Retain count before release: 3
Retain count before release: 2
#
Retain count after retain: 2
2
Retain count before release: 2
Retain count before release: 1
Retain count before dealloc: 1
这基本上是您所期望的,但是当您将对象传递给函数时获得临时所有权时,每个 CFGetRetainCount
周围都有额外的保留和释放。
这是您永远不应该读取 retainCount
值的示例之一。它没有调试值(value),documentation 中也提到了这一点。 .
关于ios - 为什么 Obj-C 实例有 1 个保留计数刚创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38367255/