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 nsfetchedresultscontroller
s in main context fire.
Comments
Post a Comment