cocoa touch - Core Data: NSManagedObjectContext Not Saved / Fetch Request Fails Until App Quits & Relaunches -


i've got core data backend that's exhibiting strange behavior. first time run app (in simulator) nsfetchrequest never find matches when given identical items multiple times in row (it return 'no results' each request proceed insert duplicate info database - can see happen because have tableview tied database).

if "quit" app pressing home button re-open app. starts behaving expected (returning results appropriate). can delete app , run again xcode reset process beginning. seems doesn't save database until app closes though i'm calling save on nsmanagedobjectcontext (which returning true).

what's going on here? how make work expected? i'm thinking i'm not saving changes nsmanagedobjectcontext how do that?

here's function fetches/returns object out of nsmanagedobjectcontext:

+ (mark *)markwithtwlinfo:(nsdictionary *)markdictionary    inmanagedobjectcontext:(nsmanagedobjectcontext *)context {     mark *mark = nil;      nslog(@"starting operation key: %@", [markdictionary[js_mark_id] description]);      // build fetch request see if can find mark in database.     nsfetchrequest *request = [nsfetchrequest fetchrequestwithentityname:@"mark"];     request.sortdescriptors = @[[nssortdescriptor sortdescriptorwithkey:@"title" ascending:yes]];     request.predicate = [nspredicate predicatewithformat:@"idunique = %@", [markdictionary[js_mark_id] description]];      // execute fetch      nserror *error = nil;     nsarray *matches = [context executefetchrequest:request error:&error];      // check happened in fetch      if (!matches || ([matches count] > 1) || error ) {  // nil means fetch failed; more 1 impossible (unique!)         // handle error         if (error) {             nslog(@"fetch error: %@", [error description]);         } else {             nslog(@"found no/multiple matches key: %@", [markdictionary[js_mark_id] description]);         }     } else if (![matches count]) { // none found, let's create mark          nslog(@"inserting: %@", [markdictionary[js_mark_id] description]);          mark = [nsentitydescription insertnewobjectforentityforname:@"mark" inmanagedobjectcontext:context];         mark.idunique   = [nsnumber numberwithint:[markdictionary[js_mark_id] intvalue]];          //save changes; returns true         if ([context save:&error]) {             nslog(@"saved true");         } else {             nslog(@"saved false");         }          if (error) {             nslog(@"save error: %@", [error description]);         }     } else { // found mark, return list of matches (which there 1 of)         nslog(@"found existing object key: %@", [markdictionary[js_mark_id] description]);         mark = [matches lastobject];     }     return mark; } 

i call function every mark want insert:

for (nsdictionary *mark in results) {     if (demo_logging) nslog(@"inserting: %@",[mark objectforkey:@"mark"]);     [self.managedobjectcontext performblock:^{         [mark markwithtwlinfo:[mark objectforkey:@"mark"] inmanagedobjectcontext:self.managedobjectcontext];     }]; } 

here's see in log when run problem:

-start app fresh database:

2013-05-05 16:45:08.105 towatchlist[10155:c07] starting operation key: 731 2013-05-05 16:45:08.106 towatchlist[10155:c07] inserting: 731 2013-05-05 16:45:08.111 towatchlist[10155:c07] saved true 2013-05-05 16:45:10.651 towatchlist[10155:c07] starting operation key: 731 2013-05-05 16:45:10.652 towatchlist[10155:c07] inserting: 731 2013-05-05 16:45:10.654 towatchlist[10155:c07] saved true 

-quit , relaunch program here

2013-05-05 16:45:29.816 towatchlist[10155:c07] starting operation key: 731 2013-05-05 16:45:29.817 towatchlist[10155:c07] found no/multiple matches key: 731 

-now nsfetchrequest returns 2 previous entries expected, should have seen first 1 when tried insert second.

my guess have parent context self.managedobjectcontext.

if case, in order ensure uniqueness of property, have save way store (recursively save until no parentcontext exists).

note must wait save complete on parent contexts before can ensure uniqueness.

replace [context save:&error] with:

nsmanagedobjectcontext* c = context; __block bool success = yes; while (c && success) {     [c performblockandwait:^{         success = [c save:&error];         //handle save success/failure     }];     c = c.parentcontext; } 

Comments