ios - Managed object context not merging changes from background context -
i have dual managed object context setup have parent/child moc relationship. parent responsible writing directly database on private queue (nsprivatequeueconcurrencytype) , have child context responsible pulling , saving data main thread (nsmainqueueconcurrencytype).
the contexts work should in when make changes main queue context , save it, changes merged background queue context , written database on background thread.
the issue having when write data directly background queue context , try merge main queue context. objects stored correctly in store, , when merge changes seems work. however, if attempt make nsfetchrequest against main queue context directly after saving data store, data stale , not correct updated data.
below code excerpts should give idea of doing. things note logic returns nsmanagedobjects json work correctly. also, have tested , mergechangesfromcontextdidsavenotification runs before ui attempts make fetch requests against main queue moc. have ideas going on?
// context setup - (nsmanagedobjectcontext *)backgroundwritermanagedobjectcontext { if (_backgroundwritermanagedobjectcontext != nil) return _backgroundwritermanagedobjectcontext; nspersistentstorecoordinator *coordinator = [self persistentstorecoordinator]; if (coordinator != nil) { _backgroundwritermanagedobjectcontext = [[nsmanagedobjectcontext alloc] initwithconcurrencytype:nsprivatequeueconcurrencytype]; _backgroundwritermanagedobjectcontext.persistentstorecoordinator = coordinator; _backgroundwritermanagedobjectcontext.mergepolicy = nsmergebypropertystoretrumpmergepolicy; _backgroundwritermanagedobjectcontext.undomanager = nil; } return _backgroundwritermanagedobjectcontext; } - (nsmanagedobjectcontext *)managedobjectcontext { if (_managedobjectcontext != nil) return _managedobjectcontext; nspersistentstorecoordinator *coordinator = [self persistentstorecoordinator]; if (coordinator != nil) { _managedobjectcontext = [[nsmanagedobjectcontext alloc] initwithconcurrencytype:nsmainqueueconcurrencytype]; _managedobjectcontext.parentcontext = _backgroundwritermanagedobjectcontext; _managedobjectcontext.mergepolicy = nsmergebypropertystoretrumpmergepolicy; _managedobjectcontext.stalenessinterval = 0.0; } return _managedobjectcontext; } // save moc - (void)savemanagedobjectcontext { @try { // perform synchronous process save main moc [_managedobjectcontext performblockandwait:^(void) { __block nserror *error = nil; // push changes in main context background writer context if (![_managedobjectcontext trylock]) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanger - unable lock managed object context: %@", error.localizeddescription]]; if (![_managedobjectcontext save:&error]) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanger - error saving managed object context: %@", error.localizeddescription]]; [_managedobjectcontext unlock]; // save background writer context [_backgroundwritermanagedobjectcontext performblock:^(void) { error = nil; if (![_backgroundwritermanagedobjectcontext trylock]) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanger - unable lock background writer managed object context: %@", error.localizeddescription]]; if (![_backgroundwritermanagedobjectcontext save:&error]) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanger - error saving background writer managed object context: %@", error.localizeddescription]]; [_backgroundwritermanagedobjectcontext unlock]; }]; }]; } @catch (nsexception *exception) { [vs_log vs_logexception:exception]; } } // code runs when attempting save objects web service call [_backgroundwritermanagedobjectcontext performblock:^(void) { // create new process object , add dictionary __block vs_coredatarequest *request = [[vs_coredatarequest alloc] init]; // .. logic here deserializes json , returns array of nsmanagedobjects // perform synchronous process save main moc @try { nserror *error = nil; [[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(mergechangesfromcontextdidsavenotification:) name:nsmanagedobjectcontextdidsavenotification object:_backgroundwritermanagedobjectcontext]; if (![_backgroundwritermanagedobjectcontext trylock]) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanger - unable lock background writer managed object context: %@", error.localizeddescription]]; if (![_backgroundwritermanagedobjectcontext save:&error]) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanger - error saving background writer managed object context: %@", error.localizeddescription]]; [_backgroundwritermanagedobjectcontext unlock]; // submit changes forground context [_managedobjectcontext performblock:^(void) { nsmutablearray *objects = [[nsmutablearray alloc] init]; // iterate through updated objects , find them in main thread moc (vs_basemanagedobject *object in request.objects) { // object main managed object context nserror *error; nsmanagedobject *obj = [_managedobjectcontext existingobjectwithid:object.objectid error:&error]; if (error) [vs_log vs_logerror:[nsstring stringwithformat:@"vs_coredatamanager - error: %@", error.localizeddescription]]; if (obj) { [_managedobjectcontext refreshobject:obj mergechanges:yes]; [objects addobject:obj]; } } // return method ui can regain control }]; } @catch (nsexception *exception) { [vs_log vs_logexception:exception]; return; } }]; // merges changes parent child context - (void)mergechangesfromcontextdidsavenotification:(nsnotification *)notification { // remove observer [[nsnotificationcenter defaultcenter] removeobserver:self name:nsmanagedobjectcontextdidsavenotification object:_backgroundwritermanagedobjectcontext]; // merge changes [_managedobjectcontext mergechangesfromcontextdidsavenotification:notification]; }
you're not calling process pending changes.
Comments
Post a Comment