ios - Where should NSManagedObjectContext be created? -


i've been learning core data , how inserts large number of objects. after learning how , solving memory leak problem met, wrote q&a memory leak large core data batch insert in swift.

after changing nsmanagedobjectcontext class property local variable , saving inserts in batches rather 1 @ time, worked lot better. memory problem cleared , speed improved.

the code posted in answer was

let batchsize = 1000  // sort of loop each batch of data insert while (therearestillmoreobjectstoadd) {      // managed object context     let managedobjectcontext = (uiapplication.sharedapplication().delegate as! appdelegate).managedobjectcontext     managedobjectcontext.undomanager = nil // if don't need undo      // next 1000 or data items want insert     let array = nextbatch(batchsize) // own implementation      // insert in batch     item in array {          // parse array item or whatever need entity attributes new object going insert         // ...          // insert new object         let newobject = nsentitydescription.insertnewobjectforentityforname("myentity", inmanagedobjectcontext: managedobjectcontext) as! mymanagedobject         newobject.attribute1 = item.whatever         newobject.attribute2 = item.whoever         newobject.attribute3 = item.whenever     }      // save context     {         try managedobjectcontext.save()     } catch {         print(error)     } } 

this method seems working me. reason asking question here, though, 2 people (who know lot more ios do) made comments don't understand.

@mundi said:

it seems in code using same managed object context, not new one.

@martinr said:

... "usual" implementation lazy property creates context once lifetime of app. in case reusing same context mundi said.

now don't understand. saying am using same managed object context or should use same managed object context? if am using same one, how create new 1 on each while loop? or if should using 1 global context, how do without causing memory leaks?

previously, had declared context in view controller, initialized in viewdidload, passed parameter utility class doing inserts, , used everything. after discovering big memory leak when started creating context locally.

one of other reasons started creating contexts locally because documentation said:

first, should typically create separate managed object context import, , set undo manager nil. (contexts not particularly expensive create, if cache persistent store coordinator can use different contexts different working sets or distinct operations.)

what standard way use nsmanagedobjectcontext?

now don't understand. saying using same managed object context or should use same managed object context? if using same one, how create new 1 on each while loop? or if should using 1 global context, how do without causing memory leaks?

let's @ first part of code...

while (therearestillmoreobjectstoadd) {     let managedobjectcontext = (uiapplication.sharedapplication().delegate as! appdelegate).managedobjectcontext     managedobjectcontext.undomanager = nil 

now, since appears keeping moc in app delegate, it's using template-generated core data access code. if not, highly unlikely managedobjectcontext access method returning new moc each time called.

your managedobjectcontext variable merely reference moc living in app delegate. thus, each time through loop, merely making copy of reference. object being referenced exact same object each time through loop.

thus, think saying not using separate contexts, , think right. instead, using new reference same context each time through loop.


now, next set of questions have performance. other post references content. go , @ again.

what saying if want big import, should create separate context, import (objective c since have not yet made time learn swift).

nsmanagedobjectcontext moc = [[nsmanagedobjectcontext alloc]     initwithconcurrencytype:nsprivatequeueconcurrencytype]; 

you attach moc persistent store coordinator. using performblock then, in separate thread, import objects.

the batching concept correct. should keep that. however, should wrap each batch in auto release pool. know can in swift... i'm not sure if exact syntax, think it's close...

autoreleasepool {     item in array {         let newobject = nsentitydescription.insertnewobjectforentityforname ...         newobject.attribute1 = item.whatever         newobject.attribute2 = item.whoever         newobject.attribute3 = item.whenever     } } 

in pseudo-code, this...

moc = createnewmocwithprivatequeueconcurrencyandattachdirectlytopsc() moc.performblock {     while(true) {         autoreleasepool {             objects = getnextbatchofobjects()             if (!objects) { break }             foreach (obj : objects) {                 insertobjectintomoc(obj, moc)             }         }         moc.save()         moc.reset()     } } 

if wants turn pseudo-code swift, it's fine me.

the autorelease pool ensures objects autoreleased result of creating new objects released @ end of each batch. once objects released, moc should have reference objects in moc, , once save happens, moc should empty.

the trick make sure object created part of batch (including representing imported data , managed objects themselves) created inside autorelease pool.

if other stuff, fetching check duplicates, or have complex relationships, possible moc may not entirely empty.

thus, may want add swift equivalent of [moc reset] after save ensure moc indeed empty.


Comments

Popular posts from this blog

dns - How To Use Custom Nameserver On Free Cloudflare? -

python - Pygame screen.blit not working -

c# - Web API response xml language -