弱属性无法使用ARC归零 [英] Weak property not zeroing using ARC

查看:78
本文介绍了弱属性无法使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆