Objective C属性与ivar与Core Data的问题

时间:2011-04-30 17:52:59

标签: objective-c ios core-data scope

我花了几个小时试图找出这个问题,我认为这归结于我对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的书籍章节并回溯我的变量以便它有意义?

2 个答案:

答案 0 :(得分:0)

根据提供的有限代码,我无法确定,但对崩溃的最简单解释是,在执行任何操作之前,您不会检查divsdivisions数组是否为空对他们的操作。

如果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,该控制器针对该任务进行了优化。