I think I'm in the most terrible problem ever than before. I'm trying to resolve an app that implement CoreData and multi-threading that fetch and modify data in background. The app also has complicated relationship between objects.
I have some majors questions:
1/ Should I turn to SQlite ? Working with CoreData and Multithread (make them thread-safe) is really pain in the ass.
2/ if I have to keep using CoreData, which method will be the best as provided by Apple
+ single persistent coordinator - many context => easy get trouble with "relationship between object" problem even I tried to update context via saved-notification.
+ use different context and persistent coordinate for each thread
In the end, I appreciate for any best practices with example/demo.
Thanks,
Quan
--
You received this message because you are subscribed to the Google Groups "Australian Cocoaheads" group.
To post to this group, send email to cocoah...@googlegroups.com.
To unsubscribe from this group, send email to cocoaheadsau...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cocoaheadsau?hl=en.
1. No, sqlite won't magically solve your multi threading issues. CoreData works great multi-threaded, you just need to follow Apple's rules and use it properly.
2. Use a single persistent coordinator. In each thread, create a managed object context, do the work and save it, then throw the moc away. Make sure each moc is created in the thread where it is needed and only used in the thread it is created. Don't pass managed objects between threads (as each are linked to a specific moc). Register for NSManagedObjectContextDidSaveNotification and merge any background thread changes to main thread moc (-[moc mergeChangesFromContextDidSaveNotification:]).
IMO you will be much better off in the long run learning to use Core Data directly than using an even higher level abstraction like MagicalRecord. Once you get the hang of it, CoreData works really well, I use it for all apps, large and small.
Cheers,
Chris
On 20/03/2012, at 5:12 AM, Do Hoang Minh Quan wrote:
--
You received this message because you are subscribed to the Google Groups "Australian Cocoaheads" group.
To post to this group, send email to cocoah...@googlegroups.com.
To unsubscribe from this group, send email to cocoaheadsau...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cocoaheadsau?hl=en.
On 20/03/2012, at 9:55 AM, Chris Miles wrote:
> If you request the objectID of a managed object before you have persisted it ([moc save:]) then you will only get back temporary IDs, which is presumably why you needed to force the creation of permanent IDs (which partially persists the object anyway). I prefer saving the moc first, before fetching any objectIDs, as then they will be permanent IDs.
>
> You probably know all that already. So curious as to the logic that requires you to fetch objectIDs before calling save (I've never had a need for it).
There were two reasons —
1. I was batching up changes to my objects and only saving every nth cycle (potentially unnecessary);
2. I recall there being a nasty bug in iOS 5.0 around relationships in Core Data that this method worked around. I cannot for the life of me find the Stack Overflow thread that outlined the problem and this as a fix, though — so take it with a grain of salt :)
It definitely solved some referential integrity errors I was having with saving my model after a specific bunch of changes.
-t
Thank you very much for your help. I decided to create a second thread and turn all performSelectorInBackground to performSelector in second thread. Beside, I merged information from change notification between 2 contexts and it works very well. No problem at all.
Thanks,
Quan
On 27/03/2012, at 9:03 AM, Simon Harris wrote:
> I've thus far avoided holding a per-thread context in a thread dictionary as I was worried it would be kept around unnecessarily - containing all the managed objects I had fetched. Instead I've been creating a context as needed, using it, then throwing it away. Is there an advantage to holding a context per thread, need I worry about the consequences of doing so?
I prefer the pattern of only creating a context when it is needed, then throwing it away when the work is complete (excluding the main thread context). The context should be linked to the task, not the thread IMO. This keeps things tidier than attempting to hold a context per thread globally. This also helps avoid the need to merge changes into a non-main thread context (see below). It is also possible (and feasible) to have more than one context per thread, in some cases.
>
> If I want to merge changes between contexts, the recommended approach is to listen for notifications to specific context rather than all contexts (presumably because system processes, etc. might also send notifications). My question is therefore, given that I will likely have many contexts in play at once, is there a recommended way to have them all listen to each other?
As you say, you can register to receive notifications from all contexts, but the docs recommend against it as you may receive notifications about private system framework Core Data changes. You could still do this and just verify the context making the change is one of yours.
However, I recommend only registering for context changes when you definitely need to merge any background changes into a context. Typically, this is only normally needed for the main thread context, so that UI is in sync with the database. If you create and destroy background task contexts as needed (i.e. keep them relatively short-lived) you will have less need to merge changes into those contexts.
Cheers,
Chris
I prefer the pattern of only creating a context when it is needed, then throwing it away when the work is complete (excluding the main thread context). The context should be linked to the task, not the thread IMO. This keeps things tidier than attempting to hold a context per thread globally. This also helps avoid the need to merge changes into a non-main thread context (see below). It is also possible (and feasible) to have more than one context per thread, in some cases.
However, I recommend only registering for context changes when you definitely need to merge any background changes into a context. Typically, this is only normally needed for the main thread context, so that UI is in sync with the database. If you create and destroy background task contexts as needed (i.e. keep them relatively short-lived) you will have less need to merge changes into those contexts.
--
You received this message because you are subscribed to the Google Groups "Australian Cocoaheads" group.
To view this discussion on the web visit https://groups.google.com/d/msg/cocoaheadsau/-/8vdnc3I6wlwJ.
setParentContext:. This means that fetch and save operations are mediated by the parent context instead of a coordinator. This pattern has a number of usage scenarios, including:nil.) In addition, a parent does not pull changes from children before it saves. You must save a child contexts if you want ultimately to commit the changes.--
You received this message because you are subscribed to the Google Groups "Australian Cocoaheads" group.
To view this discussion on the web visit https://groups.google.com/d/msg/cocoaheadsau/-/kM94kLqM0PEJ.