multithreading - iOS: Synchronizing access to CoreData -


i'm new coredata , i'm trying create simple application.

assume have function:

func saveentry(entry: entry) {    let moc = nsmanagedobjectcontext(concurrencytype: .nsprivatequeueconcurrencytype)    moc.parentcontext = savingcontext    moc.pefrormblockandwait {      // find if moc has entry     // if not => create     // else => update     // saving logic here   } } 

it can introduce problem: if call saveentry 2 threads, passing same entry duplicate it. i've added serial queue db adapter , doing in following manner:

func saveentry(entry: entry) {     dispatch_sync(serialdbqueue) { // (1)         let moc = nsmanagedobjectcontext(concurrencytype: .nsprivatequeueconcurrencytype)         moc.parentcontext = savingcontext          moc.pefrormblockandwait {  // (2)             // find if moc has entry             // if not => create             // else => update             // saving logic here         }     } } 

and works fine, until i'd add interface function:

func saveentries(entries: [entry]) {     dispatch_sync(serialdbqueue) {  // (3)         let moc = nsmanagedobjectcontext(concurrencytype: .nsprivatequeueconcurrencytype)         moc.parentcontext = savingcontext          moc.pefrormblockandwait {              entries.foreach { saveentry($0) }         }     } } 

and have deadlock: 1 called on serialdbqueue , wait till saving finishes. 2 called on private queue , wait 3. , 3 waiting 1.

so correct way handle synchronizing access? far understand it's not safe keep 1 moc , perform saves on because of reasons described here: http://saulmora.com/coredata/magicalrecord/2013/09/15/why-contextforcurrentthread-doesn-t-work-in-magicalrecord.html

i try implement single nsmanagedobjectcontext control mechanism. each context maintains serial operation queue multiple threads can call performblock: or performblockandwait: without danger of concurrent access (though must cautious of context's data changing between time block enqueued , when executes). long work within context being done on correct queue (via performblock) there's no inherent danger in enqueuing work multiple threads.

there of course complications consider , can't offer real suggestions without knowing more app.

  • what object responsible creating context , how made available every object needs it?
  • with shared context becomes difficult know when work on context "finished" (it's operation queue empty) if represents meaningful state in app.
  • with shared context more difficult abandon changes should you want discard unsaved modifications in event of error (you'll need revert changes rather discard context without saving).

Comments