我花了几个小时试图找出这个问题,我认为这归结于我对Objective C的基本理解,尽管它通过研究Core Data来体现。我并不感到惊讶 - 我现在只使用Objective C和Cocoa Touch两个月了。
我的情况是我有一系列在CD中都很好连接的模型。我的应用程序工作正常,直到我昨天尝试扩展它。我在视图控制器中将我的主模型Job作为.h文件中的类属性。在我的viewWillAppear方法中,我必须通过另一个对象查找关系,所以我做了类似的事情:
/** project as an ivar **/
NSManagedObject *project = [job valueForKey:@"project"];
NSArray *divisions = [[project valueForKey:@"divisions"] allObjects];
//do something with divisions --> crash
...
/** project as a property **/
project = [job valueForKey:@"project"];
NSArray *divisions = [[project valueForKey:@"divisions"] allObjects];
//do someting, anything ---> A-OK!
那么,当我尝试使用[project valueForKey:]的结果执行某些操作时,为什么我的应用程序崩溃,除非我将项目设为类属性?
看起来只是在那里包含if(!divisions)
条件(在视图首次加载时它应该为null),它不喜欢我在上面提供的语句并生成EXC_BAD_ACCESS
。但是,当它离开时,我的代码工作正常。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(!divisions){
NSManagedObject *project = [[job valueForKey:@"project"] retain];
NSArray *divs = [[project valueForKey:@"divisions"] allObjects];
NSSortDescriptor *alphaSort = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
divisions = [[divs sortedArrayUsingDescriptors:[NSArray arrayWithObject:alphaSort]] mutableCopy];
}
[[self tableView] reloadData];
}
我会接受存在更大的内存管理问题。我是否可以回过头来重新阅读一些关于Obj-C的书籍章节并回溯我的变量以便它有意义?
答案 0 :(得分:0)
根据提供的有限代码,我无法确定,但对崩溃的最简单解释是,在执行任何操作之前,您不会检查divs
或divisions
数组是否为空对他们的操作。
如果Project.divisions
关系为空,请执行以下操作:
NSArray *divs = [[project valueForKey:@"divisions"] allObjects];
...将返回一个空数组。任何试图解决数组的任何元素的尝试,例如[divs objectAtIndex:0]
会产生错误。
此外,divisions
似乎是控制器对象的iVar,但在将“div”数组分配给“div”数组时,您不使用首选的self.divisions
引用形式,也不使用[divisions retain]
它。由于divs
数组将被返回自动释放,因此当下一个池排空时,它将被清除,divisions
中的数组即使不为空也会消失。
只需将divisions
更改为self.divisions
即可修复。
答案 1 :(得分:-1)
除了ivar混淆之外,您的代码还有另外两个问题。访问NSManagedObject上的属性时,您应该使用primitiveValueForKey:在
中[job willAccessValueForKey:@"project"];
NSManagedObject *project = [job primitiveValueForKey:@"project"];
[job didAccessValueForKey:@"project"];
无论何时获取或设置现有托管对象的属性,都应始终在调用之前使用willAccessValueForKey:并使用didAccessValueForKey关闭:以便模型和商店保持同步。
更好的是
[job willAccessValueForKey:@"project"];
NSManagedObject *project = [job primitiveProject];
[job didAccessValueForKey:@"project"];
但不幸的是,Xcode调试器没有理解,你必须忍受那些令人讨厌的黄色警告。
此外,NSManagedObject关系返回NSSet而不是数组:
[project willAccessValueForKey:@"divisions"];
NSSet *divisions = [project primitiveValueForKey:@"divisions"];
[project didAccessValueForKey:@"divisions"];
在Apple的Model Object Implementation Guide
中阅读更多内容最后,如果您正在完成所有这些以填充表格,那么您最好不要实例化NSFetchedResultsController,该控制器针对该任务进行了优化。