弱属性无法使用ARC归零 [英] Weak property not zeroing using ARC
问题描述
对于持有弱引用的对象,我有以下简单代码:
I have the following simple code for an object that holds a weak reference:
//接口
@interface GMWeakRefObj : NSObject
@property (weak) id object;
@end
//实现
@implementation GMWeakRefObj
@synthesize object;
@end
当我运行以下测试代码时,它在第二个断言上失败:
When I run the following test code it fails on the second assert:
NSData* d = [[NSData alloc] init];
GMWeakRefObj* weakRef = [[GMWeakRefObj alloc] init];
weakRef.object = d;
NSAssert(weakRef.object != nil, @"Reference wasn't assigned");
d = nil;
NSAssert(weakRef.object == nil, @"Reference wasn't zeroed"); // <-- FAIL
ARC弱引用不是应该归零吗?如果是这样,我在做什么错了?
Aren't ARC weak references supposed to be zeroing? And if so what am I doing wrong?
推荐答案
为d
尝试一些自定义类而不是NSData
,例如MyData
.在其中实现dealloc
方法并在其中设置断点.您会看到,dealloc
在最后一个NSAssert
之后由自动释放池 调用.仅在该周之后,引用将变为nil
.
Try some custom class class instead of NSData
for d
, e.g. MyData
. Implement dealloc
method in it and set breakpoint in it. You will see, that dealloc
is called by autorelease pool after the last NSAssert
. Only after that week reference will become nil
.
添加: 看来我必须扩展我的答案才能清楚说明为什么它会那样工作. 首先,让我们看看您的示例(来自评论):
ADD: Looks like I have to extend my answer to make it clear, why it works that way. First, lets look at your example (from comments):
NSData* data = [[NSData alloc] init];
__weak NSData* weakRef = data;
data = nil;
NSAssert(weakRef == nil, @"Failed to zero");
它按预期方式工作,data = nil
之后,weakRef
变为nil
.下一个示例也适用:
It works as expected, weakRef
become nil
after data = nil
. The next example works too:
NSData* data = [[NSData alloc] init];
__weak NSData* weakRef = data;
NSLog(@"%@", data);
data = nil;
NSAssert(weakRef == nil, @"Failed to zero");
但是最后一个示例不起作用:
But the last example doesn't work:
NSData* data = [[NSData alloc] init];
__weak NSData* weakRef = data;
NSLog(@"%@", weakRef);
data = nil;
NSAssert(weakRef == nil, @"Failed to zero");
唯一的区别是我们使用弱引用来输出日志.为什么?
The only difference is that we use weak reference to output log. Why?
(其他答案可能是错误的:))
想象您NSLog
(或我们在data = nil
之前调用的任何其他函数/选择器)依赖于它的参数不是nil
.例如,它具有"if(arg == nil)return;".一开始.
Imaging that you NSLog
(or any other function/selector we call before data = nil
) rely on it's argument not to be nil
. For example, it has "if (arg == nil) return;" at the very beginning.
在多线程环境中,弱引用可以在 if
之后成为nil
.
In multithreaded environment weak reference can become nil
after if
.
因此正确编写的函数应如下所示:
So properly written function should look like:
// ...
T* local_arg = arg; // NOTE: it is strong!
if (local_arg == nil)
return;
// work with local_arg here, not with arg
// ...
但是通常我们不想在任何地方都这样做-这将是丑陋的.因此,我们要确保论点不会在中间的某个地方消失.编译器通过自动释放弱引用为我们做到这一点.
But usually we don't want to do it everywhere -- it will be ugly. So we want to be sure that arguments will not disappear somewhere in the middle. Compiler does it for us by autoreleasing weak reference.
因此,应该清楚为什么GMWeakRefObj
测试用例不起作用-在调用setObject
setter之前会自动释放weakRef
.
So, it should be clear how, why your GMWeakRefObj
test case doesn't work -- weakRef
is autoreleased before calling setObject
setter.
这篇关于弱属性无法使用ARC归零的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!