ios - 为什么 Obj-C 实例有 1 个保留计数刚创建?

标签 ios objective-c swift automatic-ref-counting

我正在研究 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/

相关文章:

objective-c - SKLabelNode 定位未按预期工作

ios - 自定义模式演示中的 UIBlurEffect

iphone - 无法在 iPhone 应用程序中使用自定义字体

ios - 在Apple Review之前获取App Store URL

ios - 在背景中为 map 添加注释

json - 返回分成不同值的 json 数据 Swift 4

ios - AWS 用户池设置 (Swift)

objective-c - 奇怪的 Objective-C/C `enum` 行为

swift - 如何使用 Swift 3 GCD 处理许多 API 调用

ios - Xcode 8.1 中的 "Segmentation fault: 11"