我正在编写一个项目,其中一项非常简单的任务偶尔会失败。着迷于这个结果,并好奇地看到你们所做的一切。
我有一个包含大型数据集的项目,我正在创建并显示一个模态窗口,以显示有关新类实例的一些详细信息。所以我有一个带有自定义窗口控制器类的窗口,代码如下:
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;没有在后台运行的代码可能与类有关(它是一个单线程模式窗口);这个班没有任何约束力。它只是...不起作用。这就像窗口类的代码在运行几次之后才能正常运行。
世界上发生了什么?有没有人甚至冒险猜测可以解释这种行为?
答案 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
这意味着保留了我分配的任何内容,因此,因为至少有一个对象拥有它,我可以将它分配给我的弱实例变量。