2011-11-17 78 views
0

例如加载一个实体关系的一组对象:核心数据错误:如何正确

我有两个实体命名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 Objects使用另一个获取请求会更好吗?

UPDATE:

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

(a)中获得的对象的计数, (b)中存在的表视图内的每个待办事项条目行,和 (c)确定所选择的条目待办事项(扔行选择)

+0

有两件事你需要检查以帮助你调试。首先,'selectedProject'是一个有效的对象,当你调用崩溃的行时?其次,selectedProject的'todos'属性/关系是否返回NSSet或nil?如果返回nil,那么当您询问该集合的所有对象时,该应用程序将会崩溃。 – Carter

+0

我添加了这些行来检索你所问的信息,但是因为它没有设法再次崩溃。正如我所说的那样,这种情况非常罕见且难以预测。当它发生时,我会发布发生的事情.Thx –

回答

2

回答#1

当你将所有的东西都拉出到一个数组中时,最好对它们进行排序。这将让您的用户体验是一致的:

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

回答#2

没有,这一比例仅为访问的关系抓取是昂贵的。取指将打到磁盘等。

+0

根据对问题 –

+0

的更改,更新了答案好,非常感谢!最后一个问题:为什么我不应该使用'allObjects'方法?你可以看到如上所述的错误吗? –

+0

@ d.ennis因为结果未确定。您可以使用该方法,但仍需要对其进行排序,否则用户体验将受到影响。如果您打算将它们放入数组中,请对数组进行排序。 –

0

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

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

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

默认情况下,“todos”关系作为错误状态返回,当您访问项目属性“todos:”时,它实际上会触发第一次从持久性存储中获取内容,核心数据可能稍后将这些“todos”所以你将在未来获得快速访问(除非你重置NSManagedObjectContext)

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