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 onsearchq
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
Post a Comment