核心数据错误:如何正确加载实体关系对象集

时间:2011-11-17 23:30:09

标签: iphone objective-c ios core-data nsfetchrequest

例如:

我有两个名为ProjectTodo的实体,其中一个项目有许多待办事项(多对多关系),每个待办事项都有一个项目(见图片)。

CoreData setup of entities

在我的ViewController.h我有类似的内容:

...
NSArray *projectArray;
NSArray *todosArray;

@property (nonatomic,retain) NSArray *projectArray;
@property (nonatomic,retain) NSArray *todosArray;
...

在我的ViewController.m我有类似的内容:

...
@synthesize projectArray,todosArray;
...
self.projectArray = [self fetchRequestForAllProjects];
...

用户有一个界面,他可以在所有不同的项目之间进行选择。一旦用户选择了一个项目,就必须将相关的待办事项对象设置为加载并显示。

问题1:如何以最佳方式将这组待办事项加载到todosArray

我这样做(也在ViewController.m):

...
// after deselecting a project entry I reset the todosArray
self.todosArray = nil;
...
//when the user selects a new project I reset the todosArray like this:
self.todosArray = [selectedProject.todos allObjects];
...

但不知何故,应用程序很少在最后一行代码中崩溃。我的代码有问题吗?

问题2 :对todos对象使用另一个获取请求会更好吗?

更新

我在todosArray的各种方法中使用ViewController.m

(a)得到物品的数量,  (b)在表视图行中显示每个todos条目  (c)识别所选择的待办事项(投掷行选择)

2 个答案:

答案 0 :(得分:2)

回答#1

最好在将所有内容从集合中拉出来进行排序。这将使您的用户体验保持一致:

NSSet *projectTodoEntities = [mySelectedProject valueForKey:@"todos"];
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"myKey" ascending:YES];
NSArray *sortedToDos = [projectTodoEntities sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];

回答#2

不,与仅访问关系相比,提取费用昂贵。获取将访问磁盘等

答案 1 :(得分:0)

对于答案#1。 1)。请确保selectProject是否在其他线程上被删除,如果删除,核心数据会将此NSManagedObject标记为无效,当您尝试访问此对象的属性时,将抛出NSObjectInaccessibleException。 2)。当您访问" todos"所有NSManagedObject关联NSManagedObjectContext,上下文限制在某些线程或线程队列上。当关系处于故障状态时,它会触发从持久存储中获取,你必须确保执行线程是否对NSManagedObjectContext有效,否则你应该使用下面的代码。

NSManagedObjectContext *context = [selectedProject managedObjectContext];
__weak YouControllerClass *weakSelf;
[context performBlockAndWait:^{
    weakSelf.todosArray = [selectedProject.todos allObjects];
}];

答案#2:对todos对象使用其他获取请求会更好吗?

默认情况下," todos"关系作为故障状态返回,当你访问项目属性" todos:时,它实际上是第一次触发从持久存储中获取,核心数据可以缓存这些" todos"稍后在内存中的对象,因此您将来可以快速访问(除非您重置NSManagedObjectContext)

对于大多数情况,例如用户检查他的限制待办事项列表,可以触发另一个获取请求,如果todo对象中没有巨大的blob数据,则性能不是真正的问题。 对于性能关键场景,比如使用核心数据来保存数百张照片和元数据作为关系,当您根据照片对象的高度,宽度或URL属性在UIView上绘制所有这些照片时,您可以考虑预取照片元素以避免性能打击(操作)。