Thursday, 15 March 2012

iphone - Persisted item in one context but Core Data can't find item in another context? -



iphone - Persisted item in one context but Core Data can't find item in another context? -

in app, have next method check next item display,

- (void)displayifpossible:(nsnumber *)orderid { nsparameterassert(orderid); nslog(@"displayifpossible orderid:%@", [orderid stringvalue]); itemstore *itemstore = [itemstore sharedinstance]; item *currentitem = [itemstore getitembyorderid:orderid]; if (!currentitem) { nslog(@"fetching next(): currentitem doens't exist"); dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{ [itemstore fetchitemsforfeed:^{ // todo fixme figure out why there's infinite recursion here // temp fix: run app once, fetch, stop run again. [self displayifpossible:orderid]; } withfailureblock:^{ [self updatestatus:@"failed fetch new items"]; }]; }); return; } self.item = currentitem; }

if currentitem doesn't exist, fetchitems query server , persist core data. when fetchitems has finished, execute callback displayifpossible again.

this fetchitems

- (void)fetchitems:(void (^)(void))callback withfailureblock:(void (^)(void))failureblock withrequestpath:(nsstring *)path withstatus:(nsnumber *)status { apiclient *client = [apiclient sharedmanager]; nsmutableurlrequest *request = [client requestwithmethod:@"get" path:path parameters:nil]; afjsonrequestoperation *operation = \ [afjsonrequestoperation jsonrequestoperationwithrequest:request success:^(nsurlrequest *request, nshttpurlresponse *response, id json) { // create new managed object context , set persistent store coordinator // note **must** done here because context belongs thread appdelegate *thedelegate = [[uiapplication sharedapplication] delegate]; nsmanagedobjectcontext *localcontext = [[nsmanagedobjectcontext alloc] init]; [localcontext setpersistentstorecoordinator:[thedelegate persistentstorecoordinator]]; (id itemjson in json) { item *item = [[itemstore sharedinstance] getitembycid:null_to_nil([itemjson valueforkey:@"id"])]; if (item == nil) { item *newitem = [nsentitydescription insertnewobjectforentityforname:@"item" \ inmanagedobjectcontext:localcontext]; newitem.cid = null_to_nil([itemjson valueforkey:@"id"]); newitem.title = null_to_nil([itemjson valueforkey:@"title"]); newitem.url = null_to_nil([itemjson valueforkey:@"url"]); newitem.image_url = null_to_nil([itemjson valueforkey:@"image_url"]); newitem.order_id = @([[self largestorderid] intvalue] + 1); newitem.status = status; nserror *error; if (![localcontext save:&error]) { nslog(@"error saving: %@", [error localizeddescription]); } else { nslog(@"fetchitems persisting item cid:%@ order_id:%@", newitem.cid, newitem.order_id); } } } if (callback != nil) { callback(); } } failure:^(nsurlrequest *request , nsurlresponse *response , nserror *error , id json) { if (failureblock) { failureblock(); } nslog(@"[itemstore fetchitems] failed. error:%@ response:%@ json:%@", [error localizeddescription], response, json); }]; [operation start]; }

so seeing infinite recursion here:

2013-02-18 12:10:07.013 giordano.iphone[5946:c07] unknown class lik in interface builder file. 2013-02-18 12:10:07.040 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:07.041 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:07.483 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:07.484 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:07.885 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:07.886 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:08.325 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:08.326 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:08.762 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:08.763 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:09.169 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:09.170 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:09.614 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:09.615 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:10.116 giordano.iphone[5946:c07] displayifpossible orderid:0 2013-02-18 12:10:10.116 giordano.iphone[5946:c07] fetching next(): currentitem doens't exist 2013-02-18 12:10:10.654 giordano.iphone[5946:c07] displayifpossible orderid:0

i opened sqlite database , can see items have indeed been inserted database.

i know multithreading , core info can tricky, , think have followed principles outlined apple's concurrency core info doc.

any ideas why displayifpossible not seeing right thing?

edit

code getitembyorderid

// returns newly generated managedobjectcontext. utilize cases without concurrency. - (nsmanagedobjectcontext *)managedobjectcontext { homecoming [(appdelegate *)[[uiapplication sharedapplication] delegate] managedobjectcontext]; } - (item *)getitembypredicate:(nspredicate *)predicate { nsfetchrequest *request = [[nsfetchrequest alloc] init]; nsentitydescription *entity = [nsentitydescription entityforname:@"item" inmanagedobjectcontext:[self managedobjectcontext]]; [request setentity:entity]; [request setresulttype:nsmanagedobjectresulttype]; [request setfetchlimit:1]; nssortdescriptor *d = [[nssortdescriptor alloc] initwithkey:@"order_id" ascending:yes selector:nil]; [request setsortdescriptors:[nsarray arraywithobject:d]]; [request setpredicate:predicate]; item *ret = nil; nserror *error; nsarray *objects = [[self managedobjectcontext] executefetchrequest:request error:&error]; if (objects == nil) { // handle error } else { if ([objects count] > 0) { ret = (item *)[objects objectatindex:0]; } else if ([objects count] > 1) { [nsexception raise:@"duplicated results in core data" format:@"%@", predicate]; } } homecoming ret; } - (item *)getitembyorderid:(nsnumber *)orderid { nsparameterassert(orderid); homecoming [self getitembypredicate:[nspredicate predicatewithformat:@"order_id = %@", orderid]]; }

a context not know changes in other contexts, unless pushed kid context. in case should hear nsmanagedobjectcontextdidsavenotification context save persistent store , merge changes. way spawn kid context in nsoperation, force changes it's parent (the 1 utilize display items) when fetch done, that's totally , depends on app design.

iphone objective-c multithreading cocoa core-data

No comments:

Post a Comment