Objective c EXC_从大纲视图访问错误视图:子项:ofItem

Objective c EXC_从大纲视图访问错误视图:子项:ofItem,objective-c,cocoa,nsoutlineview,Objective C,Cocoa,Nsoutlineview,请解释为什么我对下面我已注释掉的行有问题 它导致outlineView:objectValueForTableColumn:byItem:中的EXC_错误访问 完整课程的要点见: -(id)outlineView:(NSOutlineView*)outlineView子项:(NSInteger)项的索引:(id)项 { 如果(!项){ 项目=自身数据; } id returnValue=@; if([item isKindOfClass:[NSArray class]]){ returnValu

请解释为什么我对下面我已注释掉的行有问题

它导致outlineView:objectValueForTableColumn:byItem:中的EXC_错误访问

完整课程的要点见:

-(id)outlineView:(NSOutlineView*)outlineView子项:(NSInteger)项的索引:(id)项
{
如果(!项){
项目=自身数据;
}
id returnValue=@;
if([item isKindOfClass:[NSArray class]]){
returnValue=@“value”/[item objectAtIndex:index];
}
//return@{@“index”:@(index),@“value”:returnValue};//在outlineView:objectValueForTableColumn:byItem中生成EXC_BAD_访问:
返回值;
}

我已经尝试过用这个数据源创建一个真正基本的项目,但我仍然看到了问题所在。

一般来说,不需要初始化就可以返回一个值是很糟糕的做法

id返回值;应该是id returnValue=nil; 具体地说,如果self.data中有一个对象实际上不是NSArray(或其子对象),那么您将返回一个指向该对象的未定义指针,这几乎肯定会导致不幸的结果

您如何保证索引实际上在项目的范围内?
这似乎会产生错误的访问异常?

一般来说,不需要初始化就可以返回一个值是不好的做法

id返回值;应该是id returnValue=nil; 具体地说,如果self.data中有一个对象实际上不是NSArray(或其子对象),那么您将返回一个指向该对象的未定义指针,这几乎肯定会导致不幸的结果

您如何保证索引实际上在项目的范围内?
这似乎会生成错误的访问异常?

您不能在
outlineView:child:ofItem:
中动态生成项目。您的所有项目必须已经存在,或者至少在删除(即代表用户从视图和模型中删除)之前,或者在大纲视图显示的任何内容被取消(例如,文档关闭)之前继续存在

字典文本(
@{…}
)表示在该点创建字典。每当您的程序到达该行时,它都会创建一个新字典,每次,即使是为同一项的同一子项。(当字典中包含一些非常量的内容时,如
index
returnValue
的值时,这一点必然成立)

但是,即使您保留了字典,为您的模型使用普通的旧字典和/或数组也会很快产生非常复杂的代码

解决方案 创建具有两个属性的NSObject的简单子类:

  • (或更具体的值),它是您在大纲视图中显示的任何类型的值
  • 子项
    (或更具体的内容),它是每个项可能包含的任何子项的数组
然后保留这些对象的数组。当询问
nil
的子对象时,返回该数组中的一个对象。当询问某个项的子项时,该项将是这些对象之一,因此返回其
子项之一

当询问某个项目的对象值(我假设它是您唯一的一列)时,返回该项目的
。如果有多列,请为每列指定一个属性

最重要的是,在大纲视图可见之前创建所有这些对象,并将它们保留在周围,直到您使用完它们(无论是通过删除项目还是取消视图)。不要根据需要创建项目,然后期望大纲视图为您保留这些项目,这不是它的工作;这是你作为控制员的工作

项目不必都是同一类;如果对你的应用程序有意义,你可以让Foos拥有酒吧,让Bars拥有Bazzes。如果你的需求很简单,那么一切都成为Foo可能更有意义。做任何有意义的事。无论哪种方式,自定义对象都会使代码更加清晰


更重要的是,当您将自定义对象放到地板上时,这一点也比将由文字创建的词典放到地板上时要明显得多。查看
返回[[Foo alloc]init…]
并提醒“哦,对了,我需要坚持到底。”

您不能在
大纲视图:child:ofItem:
中动态创建项目。您的所有项目必须已经存在,或者至少在删除(即代表用户从视图和模型中删除)之前,或者在大纲视图显示的任何内容被取消(例如,文档关闭)之前继续存在

字典文本(
@{…}
)表示在该点创建字典。每当您的程序到达该行时,它都会创建一个新字典,每次,即使是为同一项的同一子项。(当字典中包含一些非常量的内容时,如
index
returnValue
的值时,这一点必然成立)

但是,即使您保留了字典,为您的模型使用普通的旧字典和/或数组也会很快产生非常复杂的代码

解决方案 创建具有两个属性的NSObject的简单子类:

  • (或更具体的值),它是您在大纲视图中显示的任何类型的值
  • 子项
    (或更具体的内容),它是每个项可能包含的任何子项的数组
然后保留这些对象的数组。当询问
nil
的子对象时,返回该数组中的一个对象。当询问某个项的子项时,该项将是这些对象之一,因此返回其
子项之一

当问到o