Objective c 调用标识符为:owner:的makeViewWithIdentifier会导致ARC重新创建ivar
我正在编写一个沙盒ARC应用程序,它带有一个基于视图的NSTableView,可以接受拖放的文件(Objective c 调用标识符为:owner:的makeViewWithIdentifier会导致ARC重新创建ivar,objective-c,automatic-ref-counting,nstableview,Objective C,Automatic Ref Counting,Nstableview,我正在编写一个沙盒ARC应用程序,它带有一个基于视图的NSTableView,可以接受拖放的文件(NSURLs)。我在以下NSTableViewDelegate方法中遇到了一些非常奇怪的情况: - (NSView *)tableView:(NSTableView *)tv viewForTableColumn:(NSTableColumn *)tc row:(NSInteger)row { // `files' is an NSMutableAr
NSURL
s)。我在以下NSTableViewDelegate
方法中遇到了一些非常奇怪的情况:
- (NSView *)tableView:(NSTableView *)tv
viewForTableColumn:(NSTableColumn *)tc
row:(NSInteger)row
{
// `files' is an NSMutableArray* ivar containing NSURLs
// that have been dropped into this table
NSURL *url = [files objectAtIndex:row];
NSString *fileName = [url lastPathComponent];
NSImage *icon = [self iconForURL:url];
NSTableCellView *view = [tv makeViewWithIdentifier:[tc identifier] owner:self];
[[view textField] setStringValue:fileName];
[[view imageView] setImage:icon];
return view;
}
我可以将一个文件拖动到表视图中,它会正确显示。拖动第二个文件时,出现以下错误:
*** Canceling drag because exception 'NSRangeException' (reason '*** -[__NSArrayM insertObject:atIndex:]: index 1 beyond bounds for empty array') was raised during a dragging session
***正在取消拖动,因为在拖动会话期间引发了异常“NSRangeException”(原因“***-[\uu NSArrayM insertObject:atIndex:]:索引1超出空数组的边界”)
在调试程序中,我发现在调用makeViewWithIdentifier:owner:
之后,文件变为空--实际上变成了一个新的对象实例。我假设这是我不理解的ARC的某个方面,但在我看来,对象对它自己的ivar有很强的引用(默认情况下);在我的统治下,它是如何被释放和重新创造的
我想出了两种方法来解决这个问题:
作为表单元格视图的所有者传递ivar(希望在将来的版本中它将继续保持一个强引用);或
创建一个局部变量以指向ivar的对象,并将ivar重新分配给旧对象(这显然是浪费,因为它同时创建了一个替换数组)
我错过了什么?这些解决方法应该是不必要的。调用-makeview with identifier:owner:将导致向owner发送-awakeFromNib消息。这是有文档记录的,但仅在头文件中(编辑:主文档已更新以参考此文档)
我猜想您的文件数组只是在-awakeFromNib中重新初始化
给定情况下的解决方案(加载视图原型而不是nib)只是将nil作为所有者传递。加载已注册NIB的其他实现(请参阅-registerNib:forIdentifier:)可能需要所有者,所有者可能是委托(也可能不是)。因此,可能必须检测并捕获对-awakeFromNib
的多个调用。将属性设置为标记nib加载并只执行一次所需的初始化是很简单的
请注意,此方法的Apple文档已更新以反映这一点:
请注意,每次调用此方法时都会调用awakeFromNib,
这意味着awakeFromNib也被调用在owner上,即使
主人已经醒了
是否有一个标准模式来避免这个问题——在其他地方初始化IVAR?请参阅上面更新的解决方案。-awakeFromNib
中的ivar初始化是标准。只要正确对待主人,一切都会好起来的。