Ran*_*ngo 1 objective-c retaincount
当我使用__weak指针引用NSObject时,会显示意外的retainCount.
这是代码:
id obj1 = [[NSObject alloc] init];
id __weak obj2 = obj1;
NSLog(@"obj1: %ld", CFGetRetainCount((__bridge CFTypeRef)obj1)); // line 31
NSLog(@"obj2: %ld", CFGetRetainCount((__bridge CFTypeRef)obj2)); // line 32
NSLog(@"obj1 again: %ld", CFGetRetainCount((__bridge CFTypeRef)obj1)); // line 33
Run Code Online (Sandbox Code Playgroud)
所以〜我的困惑是,obj2的retainCount预计为1,为什么retainCount为2?
我从书中读到:__ weak指针将对象注册到autoreleasepool,因此保留计数+ 1.
但是,obj1和obj2指的是相同的内存地址,在这种情况下,obj1的retainCount也应该变为2.但是,它仍然保持为1.
我知道retainCount是不可靠的,但我很好奇它是如何来的.(我的环境是Xcode 8.3.3,iOS 10.3)
非常感谢任何人都可以向初学者解释这个:)
保留计数的确切值通常是一个实现细节,它取决于编译器,Objective-C语言运行时以及所涉及的任何其他库(如Foundation).但是,只要你不依赖于这种行为,就可以理解为什么它会以这种方式运作.
你的书是错的,或者你误解了它.使用__weak不会将对象放在autoreleasepool中.
这是第32行(具有@"obj2: %ld"格式字符串的那个)发生的事情.
为了安全地将对象引用传递给函数或方法(如NSLog),它必须是一个强引用的引用.因此编译器会生成对objc_loadWeakRetainedon 的调用obj2.此函数以原子方式递增对象的保留计数并返回引用.因此,在传递对象引用之前,对象的保留计数从1到2 NSLog.
然后,在NSLog返回之后,编译器生成一个调用objc_release.因此,保留计数从第3个减少到1 NSLog.
如果您想确定发生了什么,请查看编译器的汇编器输出.你可以让Xcode向你展示:
这是大会的相关部分:
.loc 2 0 9 discriminator 1 ## /Users/mayoff/TestProjects/test/test/main.m:0:9
leaq -32(%rbp), %rdi
##DEBUG_VALUE: obj2 <- [%RBP+-32]
.loc 2 16 66 is_stmt 1 ## /Users/mayoff/TestProjects/test/test/main.m:16:66
callq _objc_loadWeakRetained
movq %rax, %rbx
Ltmp4:
.loc 2 16 29 is_stmt 0 ## /Users/mayoff/TestProjects/test/test/main.m:16:29
movq %rbx, %rdi
callq _CFGetRetainCount
movq %rax, %rcx
Ltmp5:
Ltmp20:
## BB#3:
##DEBUG_VALUE: obj2 <- [%RBP+-32]
##DEBUG_VALUE: obj1 <- %R15
Ltmp6:
.loc 2 16 9 discriminator 1 ## /Users/mayoff/TestProjects/test/test/main.m:16:9
leaq L__unnamed_cfstring_.4(%rip), %rdi
xorl %eax, %eax
movq %rcx, %rsi
callq _NSLog
Ltmp7:
Ltmp21:
## BB#4:
##DEBUG_VALUE: obj2 <- [%RBP+-32]
##DEBUG_VALUE: obj1 <- %R15
.loc 2 16 9 discriminator 2 ## /Users/mayoff/TestProjects/test/test/main.m:16:9
movq %rbx, %rdi
callq *_objc_release@GOTPCREL(%rip)
Run Code Online (Sandbox Code Playgroud)
第16行是(在我的测试中)使用的那一行obj2.您可以在呼叫objc_loadWeakRetained之前看到呼叫CFGetRetainCount,并在objc_release之后NSLog返回呼叫.
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |