ios - NSManagedObjectControllers read only access on another thread -


i selecting core data entries , sorting them. straight forward enough because of calculations in sort distance wanted put in alternate thread. did usual way making new nsmanagedobjectcontroller other thread adding code within #ifdef threads sections below.

now can fetch, sorting , organizing, without slowing user interface , table updated when ready.

but, since doing fetch in local managed object context, fetched objects not valid on main thread - in fact disappear out of table view cells.

so, questions are: 1) ok use main managed object context, since reading, , not create local context @ all? 2) should go through , re-fetch objects main managed object context on main thread using objectid values search managed object context objects after sorting , organizing? 3) should fetch on main managed object context performblockandwait keep sort , organize returned objects on searchq thread? 4) else have not thought of?

- (void) fetchshoplocations { #ifdef threads     dispatch_queue_t searchq = dispatch_queue_create( "searchqueue", null );     dispatch_async( searchq, ^{ #endif         nserror *error;  #ifdef threads         // make managed object context can not on main thread         nsmanagedobjectcontext *localcontext = [[nsmanagedobjectcontext alloc] init];         [localcontext setpersistentstorecoordinator: [self.managedobjectcontext persistentstorecoordinator]]; #else         nsmanagedobjectcontext *localcontext = self.managedobjectcontext; #endif          // array of locations sorted distance         nsarray *locations = nsfetchrequest *request = [nsfetchrequest fetchrequestwithentityname: nsstringfromclass([shop class])];         // no sort descriptors since cannot sort on things not in database          nsarray *locations = [context executefetchrequest: request error: &error];         if( !locations ) {             nslog( @"shop fetch error: %@", error );             return;         }         locations = [locations sortedarrayusingcomparator: ^nscomparisonresult( shop *loc1, shop *loc2 ) {                     double dist1 = [loc1 distancefromlatitude: self.referencelatitude andlongitude: self.referencelongitude];                     double dist2 = [loc2 distancefromlatitude: self.referencelatitude andlongitude: self.referencelongitude];                     if( dist1 < dist2 )                             return nsorderedascending;                     else if( dist1 > dist2 )                             return nsordereddescending;                     return [[loc1 name] localizedcaseinsensitivecompare: [loc2 name]];         }];          nsmutablearray *sections = [nsmutablearray arraywithcapacity: 5];         nsmutabledictionary *section;         nsmutablearray *rows;          section = [nsmutabledictionary dictionarywithcapacity: 2];         rows = [nsmutablearray arraywithcapacity: locations.count];         __block double sectionlimituserunits = 5.0;         __block double sectionlimitkilometers;         if( self.userunits == locationdistanceunitsmiles )               sectionlimitkilometers = sectionlimituserunits * kilometers_per_mile;         else  sectionlimitkilometers = sectionlimituserunits;         [section setvalue: [nsstring stringwithformat: @"within %g", sectionlimituserunits] forkey: ksectionheadertitlekey];         [locations enumerateobjectsusingblock: ^( shop *loc, nsuinteger idx, bool *stop ) {             double distance = [loc distancefromlatitude: self.referencelatitude andlongitude: self.referencelongitude];             if( distance > self.maxdistance ) {                 *stop = yes;             } else {                 while( distance > sectionlimitkilometers ) {                     [section setvalue: [rows copy] forkey: krowkey];                     [sections addobject: [section copy]];                     [section removeallobjects];                     [rows removeallobjects];                      sectionlimituserunits += 5.0;                     if( self.userunits == locationdistanceunitsmiles )                           sectionlimitkilometers = sectionlimituserunits * kilometers_per_mile;                     else  sectionlimitkilometers = sectionlimituserunits;                     [section setvalue: [nsstring stringwithformat: @"within %g", sectionlimituserunits] forkey: ksectionheadertitlekey];                 }                 [rows addobject: loc];             }         }];         [section setvalue: [rows copy] forkey: krowkey];         [sections addobject: [section copy]];  #ifdef threads         dispatch_async( dispatch_get_main_queue(), ^{ #endif             self.sections = sections;             [self.tableview reloaddata]; #ifdef threads         });     });     dispatch_release( searchq ); #endif } 

because of non-deterministic nature of threading conflicts know can't rely on testing appears work in simulator.

thanks in advance!

1) ok use main managed object context, since reading, , not create local context @ all?

no. someday, access main managed object context @ same time fetch , headache. (i have encountered deadlock doing this.)

2) should go through , re-fetch objects main managed object context on main thread using objectid values search managed object context objects after sorting , organizing?

not all objects, since using table view, need re-fetch objects displayed in table. , re-fetching objects main thread using objectid correct thing do.

3) should fetch on main managed object context performblockandwait keep sort , organize returned objects on searchq thread

this option, need understand really well how works. approach doing simpler.

4) else have not thought of?

you can avoid sorting array in code making query return locations order distance. see this answer.


Comments

Popular posts from this blog

java - Run a .jar on Heroku -

java - Jtable duplicate Rows -

validation - How to pass paramaters like unix into windows batch file -