Xcode / Cocoa:“object.property = value”偶尔会失败?有谁能解释一下?

时间:2012-08-30 01:37:58

标签: objective-c xcode variable-assignment

我正在编写一个项目,其中一项非常简单的任务偶尔会失败。着迷于这个结果,并好奇地看到你们所做的一切。

我有一个包含大型数据集的项目,我正在创建并显示一个模态窗口,以显示有关新类实例的一些详细信息。所以我有一个带有自定义窗口控制器类的窗口,代码如下:

MyWindowController.h:

#import <DataModel.h>

@interface MyWindowController : NSWindowController
@property (nonatomic, weak) FooClass *fooInstance;
@end

MyWindowController.m:

@implementation MyWindowController

@synthesize fooInstance = _fooInstance;

-(void) init {
    self = [super init];
    if (self) {
       self.fooInstance = [FooClass new];
    }
    return self;
}

@end

完全千篇一律,对吧?但是,当我第一次添加表单并运行它多次时,分配失败了一遍又一遍。 self.fooInstance一直没回来。我甚至确认FooClass初始化程序正在运行(直接通过它)并返回一个非空指针指向有效的FooClass实例。然而,在赋值行之后,self.fooInstance仍为空。

我跑了很多次,一遍又一遍地看着同样的结果。然后,我将 替换为赋值语句:

FooClass *foo = [FooClass new];
self.fooInstance = foo;

......并且任务突然开始起作用,从那以后它一直在运行。即使我将代码恢复为self.fooInstance = [FooClass new],它也能完美运行。

我简直不敢相信......直到我看到它在同一个项目中再次发生,同时为同一个类别敲打同一类型的窗口。

我不明白发生了什么。 self.fooInstance访问器完全是@synthesized;没有在后台运行的代码可能与类有关(它是一个单线程模式窗口);这个班没有任何约束力。它只是...不起作用。这就像窗口类的代码在运行几次之后才能正常运行。

世界上发生了什么?有没有人甚至冒险猜测可以解释这种行为?

1 个答案:

答案 0 :(得分:3)

我建议您仔细阅读Mike Ash's explanation of weak pointers。本节是相关的一点:

  

弱引用

     

首先,什么是弱参考?简单地说,一个弱者   reference是对象的引用(在Objective-C land中的指针)   它不参与保持该对象的活着。例如,   使用内存管理,这个setter创建一个弱引用   新对象:

- (void)setFoo: (id)newFoo
{
    _foo = newFoo;
} 
     

因为setter不使用retain,所以引用不会使新对象保持活动状态。只要它被保留,它就会活着   当然,还有其他参考文献。但是一旦那些消失了,就成了对象   即使_foo仍指向它,也会被解除分配。

好的,这解释了第一部分,但为什么第二部分有效呢?

好吧,当你编写一个像:

这样的实例变量时
FooClass *foo = //assignment

编译器对自己说“保持这个问题是一个非常好的主意,(至少直到功能超出ARC的范围),并将其转化为:

__strong FooClass *foo = //assignment

这意味着保留了我分配的任何内容,因此,因为至少有一个对象拥有它,我可以将它分配给我的弱实例变量。