Cocoa NSOutlineView(源列表)EXC\u错误\u访问错误与ARC
我有一个启用ARC的项目,在IB中我创建了一个窗口,其中包含源代码列表组件,我认为它只是一个配置的Cocoa NSOutlineView(源列表)EXC\u错误\u访问错误与ARC,cocoa,automatic-ref-counting,nsoutlineview,Cocoa,Automatic Ref Counting,Nsoutlineview,我有一个启用ARC的项目,在IB中我创建了一个窗口,其中包含源代码列表组件,我认为它只是一个配置的NSOutlineView。我正在使用神奇的委托方法: - (id)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item 对此,我根本找不到任何文档。一旦这个方法被实现,我的大纲视图中的根节点就会出现,在这个节点上我的整个模型都会被释放。然后,当我
NSOutlineView
。我正在使用神奇的委托方法:
- (id)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
对此,我根本找不到任何文档。一旦这个方法被实现,我的大纲视图中的根节点就会出现,在这个节点上我的整个模型都会被释放。然后,当我尝试展开根节点时,应用程序立即崩溃,因为模型不再存在
如果我不使用这个方法,我的模型仍然存在,源列表可以工作,但是没有一个单元格出现(可以理解)。我真的没有在这里做任何花哨的事
我以前从未遇到过ARC这样的问题,但现在已经很晚了,所以我有可能做了一些愚蠢的事情,只是看不见而已。以下是完整的代码:
@implementation RLListController
- (void)awakeFromNib
{
RLPerson *stan = [[RLPerson alloc] initWithName:@"Stan"];
RLPerson *eric = [[RLPerson alloc] initWithName:@"Eric"];
RLPerson *ken = [[RLPerson alloc] initWithName:@"Ken"];
RLPerson *andrew = [[RLPerson alloc] initWithName:@"Andrew"];
RLPerson *daniel = [[RLPerson alloc] initWithName:@"Daniel"];
RLPerson *aksel = [[RLPerson alloc] initWithName:@"Aksel"];
[stan addChild:eric];
[stan addChild:ken];
[stan addChild:andrew];
[ken addChild:daniel];
[daniel addChild:aksel];
self.people = [@[stan] mutableCopy];
}
#pragma mark - Source List dataSource
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
RLPerson *person = item;
return (item != nil) ? [person.children count] : [self.people count];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
RLPerson *person = item;
return (item != nil) ? [person.children count] > 0 : YES;
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
RLPerson *person = item;
return (item != nil) ? [person.children objectAtIndex:index] : [self.people objectAtIndex:index];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
RLPerson *person = item;
return person.name;
}
- (id)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
RLPerson *person = item;
NSTableCellView *cell = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
cell.objectValue = person;
[cell.textField setStringValue:person.name];
return cell;
}
@end
@implementation RLPerson
- (id)initWithName:(NSString *)name
{
self = [super init];
if(self)
{
_name = [name copy];
_children = [[NSMutableArray alloc] initWithCapacity:0];
}
return self;
}
- (void)addChild:(RLPerson *)child
{
[_children addObject:child];
}
- (void)dealloc
{
NSLog(@"dealloc");
}
@end
我刚刚在我的代码中发现了一个类似的崩溃。我会描述我的原因。。。我很确定这同样适用于这里,但我还没有测试过你的代码 请注意,如果您有多个NIB,则可以多次调用
awakeFromNib
。如果您在XIB文件中的NSOutlineView中嵌入了NSTableCellView对象,我相信这种情况就是如此,这些对象是在调用makeViewWithIdentifier:owner:
中的outlineView:viewForTableColumn:item:
时提取的
由于您正在awakeFromNib
中创建模型对象(stan
等),因此在这些多个调用过程中会重新创建它们。每次调用时,ARC都会清理以前的模型对象,但NSOutlineView仍在引用它们,因此,当NSOutlineView试图向它们询问更多信息时,会出现后一次崩溃
解决方法是将模型对象创建从awakeFromNib
中移出,或者移到init
方法中
更新:
还有一些小问题。。。我还花了一些时间找到magic
outlineView:viewForTableColumn:item:
方法的文档。出于某种原因,它是NSOutlineViewDelegate协议的一部分,而不是NSOutlineViewDataSource。我相信如果你实现了这个方法,你就不需要实现outlineView:objectValueForTableColumn:byItem:
当你用僵尸模板在Instruments下运行这个时会发生什么?我想我看到了同样的问题:你有没有找到这个问题的根源?@Ashley No,我放弃了这个项目。谢谢你的回复。我想我最终解决了。。。看看我的答案。