ios - Changes on Background NSManagedObjectContext not visible on Main, using NSFetchedResultsController -


this bizarre issue, , thought understood core data.

i use background context has no parent. hooked right persistent store coordinator. update objects on background context save it. listen contextdidsavenotification , merge changes main thread context. updated objects not faults on main thread used populate table view cells. expect changes merge. not.

without getting details of data models, suffices object has property "downloadstate". once parsing work done on background thread, downloadstatevalue (an enum) gets set "3", corresponds 'completed'.

i subscribe contentwillsave notification inspect what's going on. @ end of parsing work:

2016-06-13 10:19:21.055 myapp[29162:52855206] going save background context. updated:{( <qluserpinnedcourse: 0x7fe195403c10> (entity: qluserpinnedcourse; id: 0xd0000000002c0002 <x-coredata://95821adc-8a1f-4dac-b20c-edd8f8f413ea/qluserpinnedcourse/p11> ; data: {   course = "0xd000000000dc0008 <x-coredata://95821adc-8a1f-4dac-b20c-edd8f8f413ea/qlcourse/p55>";   courseid = 2794;   /* other fields redacted */ }), <qlcourse: 0x7fe1954cded0> (entity: qlcourse; id: 0xd000000000dc0008 <x-coredata://95821adc-8a1f-4dac-b20c-edd8f8f413ea/qlcourse/p55> ; data: {  /* other fields redacted*/  contentdownloadstate = 3;  courseid = 2794;  pinneduserdata = "0xd0000000002c0002 <x-coredata://95821adc-8a1f-4dac-b20c-edd8f8f413ea/qluserpinnedcourse/p11>";     }) 

the nsfetchedresultscontroller listenting qluserpinnedcourse objects gets delegate calls, triggers cell reloads in tables.

the predicate is:

// specify criteria filtering objects fetch nspredicate *predicate = [nspredicate predicatewithformat:@"pinned == %@ && course.contentdownloadstate in %@",                                   @yes,                                   @[@(qldownloadstatesucceeded), @(qldownloadstatenotyetattempted), @(qldownloadstatefailed), @(qldownloadstateincomplete)]                                   ]; 

now when cell code, have qluserpinnedcourse object work with. set breakpoint in debugger , get:

(lldb) po usercourse.course <qlcourse: 0x7fe19568f740> (entity: qlcourse; id: 0xd000000000dc0008 <x-coredata://95821adc-8a1f-4dac-b20c-edd8f8f413ea/qlcourse/p55> ; data: {      contentdownloadstate = 1;     courseid = 2794;     pinneduserdata = "0xd0000000002c0002 <x-coredata://95821adc-8a1f-4dac-b20c-edd8f8f413ea/qluserpinnedcourse/p11>"; }) 

the question is, why contentdownloadstate not 3, still 1 ?? don't it.

shouldn't these changes have been merged??

details stack:

psc -> private concurrent (saving context) -> main thread context  psc -> private concurrent (import context) 

contextdidsave: if context import context, merge changes both contexts above:

_contextsaveobserver = [[nsnotificationcenter defaultcenter] addobserverforname:nsmanagedobjectcontextdidsavenotification                                                                              object:nil                                                                               queue:nil                                                                          usingblock:^(nsnotification* note)                             {                                 nsmanagedobjectcontext *contextsaved = note.object;                                 nsmanagedobjectcontext *moc = weakself.mainqueuecontext;                                  // basically, if background worker thread                                  ddlogdebug(@"updatedobjects:%@", note.userinfo[nsupdatedobjectskey]);                                  if ([contextsaved.userinfo[coredatauserinfokeyisworkercontext] boolvalue])                                 {                                     [weakself.privatesavingcontext performblock:^(){                                          (nsmanagedobject *object in note.userinfo[nsupdatedobjectskey]) {                                             [[weakself.privatesavingcontext objectwithid:[object objectid]] willaccessvalueforkey:nil];                                         }                                          [weakself.privatesavingcontext mergechangesfromcontextdidsavenotification:note];                                          [moc performblock:^(){                                              (nsmanagedobject *object in note.userinfo[nsupdatedobjectskey]) {                                                 [[moc objectwithid:[object objectid]] willaccessvalueforkey:nil];                                             }                                              [moc mergechangesfromcontextdidsavenotification:note];                                           }];                                     }];                                 }                             }]; 

note i'm asking usercourse.course object attribute, although frc interested in qluserpinnedcourse objects. thought because specify keypath in predicate relates qlcourse object, these changes refreshed.

it's quirk of core data. need re-fault objects in main context updated save operation.

here's example in swift:

maincontext.performblock {     let updatedobjects : set<nsmanagedobject> = notification.userinfo![nsupdatedobjectskey] as! set<nsmanagedobject>      obj in updatedobjects {         self.maincontext.objectwithid(obj.objectid).willaccessvalueforkey(nil)     }      self.maincontext.mergechangesfromcontextdidsavenotification(notification) } 

the main part call willaccessvalueforkey:nil, causes object marked fault. cause nsfetchedresultscontrollers in main context fire.


Comments

Popular posts from this blog

sequelize.js - Sequelize group by with association includes id -

android - Robolectric "INTERNET permission is required" -

java - Android raising EPERM (Operation not permitted) when attempting to send UDP packet after network connection -