Reputation: 3455
For example:
I have two entities named Project
and Todo
where a project has many todos (to-many relationship) and each todo has one Project(see image).
In my ViewController.h
I have something like:
...
NSArray *projectArray;
NSArray *todosArray;
@property (nonatomic,retain) NSArray *projectArray;
@property (nonatomic,retain) NSArray *todosArray;
...
In my ViewController.m
I have something like:
...
@synthesize projectArray,todosArray;
...
self.projectArray = [self fetchRequestForAllProjects];
...
The user has an interface where he is able to select between all different projects. As soon as the user selects a project, the related todo objects have to be set to be loaded and presented.
Question 1: How do I load the set of todos into the todosArray
in the best way?
I was doing it like that (also in the 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];
...
But somehow the app very rarely crashes in the last line of code. Is there any problem with my code?
Question 2: Would it be better to use another fetch request for the todos Objects?
UPDATE:
I am using the todosArray
in various methods of the ViewController.m
:
(a) get the count of objects, (b) present each todos entry inside a table view row, and (c) to identify the selected todo entry (threw row selection)
Upvotes: 0
Views: 2071
Reputation: 2048
For answer #1. 1). Please make sure whether selectedProject is deleted on other thread, if it is deleted, core data will mark this NSManagedObject as invalid, when you try to access property of this object, a NSObjectInaccessibleException will be thrown. 2). All NSManagedObject associates NSManagedObjectContext, the context is limited on certain thread or thread queue, when you access "todos" relationship while it is in fault state, it will trigger a fetching from persistent store, you must make sure whether execution thread is valid for NSManagedObjectContext, otherwise you should use below code.
NSManagedObjectContext *context = [selectedProject managedObjectContext];
__weak YouControllerClass *weakSelf;
[context performBlockAndWait:^{
weakSelf.todosArray = [selectedProject.todos allObjects];
}];
Answer #2: Would it be better to use an other fetch request for the todos Objects?
By default the "todos" relationship is returned as fault state, when you access project property "todos:, it actually triggers fetching from persistent store for 1st time, core data may cache these "todos" objects in memory later, so you will get fast access in future (unless you reset NSManagedObjectContext)
For most scenarios, like user checks his limit todo lists, it is ok to trigger another fetch request, the performance is not real problem if there is no huge blob data in todo object. For performance critical scenarios, like use core data to save hundreds of photos and metadata as a relationship, when you draws all these photos on UIView based on height, width or URL property of photo object, you make consider pre-fetching photo meta to avoid performance hit (io operation).
Upvotes: 0
Reputation: 46718
Answer #1
It is best to sort them when you pull everything out of the set into an array. This will keep your user experience consistent:
NSSet *projectTodoEntities = [mySelectedProject valueForKey:@"todos"];
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"myKey" ascending:YES];
NSArray *sortedToDos = [projectTodoEntities sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];
Answer #2
No, fetching is expensive compared to just accessing a relationship. A fetch will hit disk, etc.
Upvotes: 2