@interface A @property (nonatomic,weak) id refObject; @end @implementation A @end
和第二类B与dealloc实现
@interface B @end @implementation B -(void) dealloc { NSLog(@"In dealloc"); } @end
最后在A班的某个地方有以下几个:
@implementation A ... -(void) foo { B* b = [B new]; self.refObject = b; // Just use b after the weak assignment // in order to not dealloc 'b' before assignement NSLog(@"%@",b); } ... @end
如果我在[B dealloc]中设置一个断点并检查[A refObject]属性,我可以看到a.refObject为零,但a-> _refObject不为零,指向’b’
任何想法为什么会发生?
解决方法
但是通过ARC运行时功能可以对每个弱指针进行访问
如果释放已经开始,则返回零.
长回答:通过设置一个观察点,您可以看到a-> _refObject在末尾设置为nil
释放过程.堆栈回溯(当观察点被击中时)看起来像这样:
frame #0: 0x00007fff8ab9f0f8 libobjc.A.dylib`arr_clear_deallocating + 83 frame #1: 0x00007fff8ab889ee libobjc.A.dylib`objc_clear_deallocating + 151 frame #2: 0x00007fff8ab88940 libobjc.A.dylib`objc_destructInstance + 121 frame #3: 0x00007fff8ab88fa0 libobjc.A.dylib`object_dispose + 22 frame #4: 0x0000000100000b27 weakdealloc`-[B dealloc](self=0x000000010010a640,_cmd=0x00007fff887f807b) + 151 at main.m:28 frame #5: 0x0000000100000bbc weakdealloc`-[A foo](self=0x0000000100108290,_cmd=0x0000000100000e6f) + 140 at main.m:41 frame #6: 0x0000000100000cf5 weakdealloc`main(argc=1,argv=0x00007fff5fbff968) + 117 at main.m:52 frame #7: 0x00007fff8c0987e1 libdyld.dylib`start + 1
和object_dispose()从 – [NSObject dealloc]调用(可以在
http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm).
因此在 – [B dealloc]中,a-> _refObject在调用(编译器生成)[super dealloc]之前不为零.
所以问题仍然存在:为什么a.refObject在这个时候返回nil?
原因是每次访问ARC编译器生成的弱指针
调用objc_loadWeak()或objc_loadWeakRetained().从documentation:
id objc_loadWeakRetained(id *object)
If object is registered as a __weak object,and the last value stored into object has not > yet been deallocated or begun deallocation,retains that value and returns it. Otherwise > returns null.
所以即使在这个时候ref- ref对象不是零,访问弱指针
通过objc_loadWeakRetained()(由属性访问器方法完成)返回nil,
因为B对象的释放已经开始了.
调试器直接访问 – > refObject,不调用objc_loadWeak().