objective-c - 弱属性不使用 ARC 归零

标签 objective-c properties automatic-ref-counting weak-references

对于持有弱引用的对象,我有以下简单代码:

//接口(interface)

@interface GMWeakRefObj : NSObject
@property (weak) id object;
@end

//实现

@implementation GMWeakRefObj 
@synthesize object;
@end

当我运行以下测试代码时,它在第二个断言上失败:

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 弱引用不是应该清零吗?如果是这样,我做错了什么?

最佳答案

尝试使用一些自定义类来代替 dNSData,例如我的数据。在其中实现dealloc方法并在其中设置断点。您将看到,dealloc 在最后一个 NSAssert 之后由自动释放池调用。只有在那一周之后,引用才会变为nil

添加: 看来我必须扩展我的答案才能弄清楚为什么它会这样工作。 首先,让我们看一下您的示例(来自评论):

NSData* data = [[NSData alloc] init];
__weak NSData* weakRef = data;
data = nil;
NSAssert(weakRef == nil, @"Failed to zero");

它按预期工作,weakRefdata = nil 后变为 nil。下一个示例也有效:

NSData* data = [[NSData alloc] init];
__weak NSData* weakRef = data;
NSLog(@"%@", data);
data = nil;
NSAssert(weakRef == nil, @"Failed to zero");

但是最后一个例子不起作用:

NSData* data = [[NSData alloc] init];
__weak NSData* weakRef = data;
NSLog(@"%@", weakRef);
data = nil;
NSAssert(weakRef == nil, @"Failed to zero");

唯一的区别是我们使用弱引用来输出日志。为什么?

(答案的其余部分可能是错误的:))

假设您NSLog(或我们在data = nil之前调用的任何其他函数/选择器)依赖于它的参数不为nil 。例如,它有“if (arg == nil) return;”在最开始的时候。

在多线程环境中,弱引用可以if之后变为nil

正确编写的函数应该如下所示:

  // ...
  T* local_arg = arg;   // NOTE: it is strong!
  if (local_arg == nil)
    return;
  // work with local_arg here, not with arg
  // ...

但通常我们不想在所有地方都这样做——这会很丑陋。所以我们要确保争论不会在中间的某个地方消失。编译器通过自动释放弱引用来为我们做到这一点。

因此,应该清楚您的 GMWeakRefObj 测试用例为何不起作用 - weakRef 在调用 setObject setter 之前自动释放.

关于objective-c - 弱属性不使用 ARC 归零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9096008/

相关文章:

java - 如何从属性文件中获取 bean 验证错误消息?

objective-c - NSURLConnectionDelegate 静态类包装器不调用函数调用 (ARC)

ios - 苹果源代码 - require( error == nil, bail ) 导致错误

ios - 手动将 nil 设置为 swift 对象以避免保留循环?

ios - 相同的字符显示不同的十六进制代码

iphone - 如何在iphone的sqlite数据库中保存用户名和密码

ios - CCActionSequence 同时运行所有 Action

c# - 具有完整属性的私有(private)字段初始化

ios - 将选定的项目值快速传递给新的 View Controller

java - 通过从另一个文件逐行读取来加载属性文件