Reputation: 10818
A lot of times I have a situation in my app where I'm pushing a view controller and fetching object from core data to fill the UI. Now I usually do this fetching in viewDidLoad on the main thread and I'm sure there is a better way to do this, maybe on different thread.
If indeed thread is the way to go here, I dont have a lot of experience with threads in objective c, so I will really appreciate if some one can show me code examples.
And also I know core data is not thread safe so should I do any extra work to be on the safe side?
Upvotes: 0
Views: 669
Reputation: 28409
You should probably be using NSFetchedResultsController. It will manage batching for you and only load what you need at the time. It's not just for table views. You can do this without a separate thread (as long as your DB isn't too big, and your fetch does not have too complex predicate that requires visiting every record in the DB).
As an alternative to FRC, or in the case of needing all records, you can use a separate thread, which will fetch objects, then present them to the main thread.
These are difficult concepts to explain in a single SO answer, so if it still does not make sense, consult the Core Data Concurrency Programming Guide.
Or, if you want to load it all, and have some control, you can do something like this. NOTE: I think this dual MOC pattern is the way to go anyway, because it makes it easier to do backgrounding anyway. For that matter, if you use UIManagedDocument, you get most of this for free anyway.
Note, this will probably take longer overall to load, but it will free up the UI thread.
NSManagedObjectContext *workerMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
workerMoc.persistentStoreCoordinator = psc;
// The "mainMoc" will be a child of the worker
NSManagedObjectContext *mainMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
mainMoc.parentContext = workerMoc;
Then when loading...
// The actual work will run in the background on the worker queue
// The "worker" queue will do the fetching and faulting, then pass object IDs
// to the mainMoc, which will fault its MOs from the parent
[workerMoc performBlock:^{
NSFetchRequest *fetchRequest = // Create fetch request
NSArray *fetchResults = [workerMoc executeFetchRequest:fetchRequest error:0];
[fetchResults enumerateObjectsUsingBlock:^(NSManagedObject *obj, NSUInteger idx, BOOL *stop) {
// Probably want to fault the object in before going to mainMoc
// since that can also take some time...
// Can also "batch" them in some small number of objects.
NSManagedObjectID *objectID = obj.objectID;
[mainMoc performBlock:^{
NSManagedObject *fetchedObject = [mainMoc objectWithID:objectID];
// Do something with it now that you are back on the main thread...
}];
}
}];
Upvotes: 2