У меня проблемы с использованием фоновых потоков для обновления данных в UIManagedDocument
/ Core Data
. В частности, я использую NSFetchResultsController
для обновления аннотаций карты на основе геокодированных данных из фонового потока (после слияния обратно в мой основной MOC), но карта никогда не обновляется из-за способа, которым UIManagedDocument
передает данные в свои хранилища и / или нескольким MOC (родительским и дочерним). Если я закрываю приложение и снова открываю, аннотации заполняются, поэтому в определенный момент происходит фиксация в постоянном хранилище, но мне неясно, как форсировать такой коммит, который, таким образом, обновит NSFetchResultsController
. Вот некоторый код:
Фоновый поток, обновляющий MOC:
- (void) populateGPSCoordsInClubsInContext: (NSManagedObjectContext *) mainCtx
{
dispatch_queue_t MapFetchQ = dispatch_queue_create("Google Map Data Fetcher", NULL);
dispatch_async(MapFetchQ, ^{
NSManagedObjectContext * ctxThread = [[NSManagedObjectContext alloc] init];
[ctxThread setPersistentStoreCoordinator:mainCtx.persistentStoreCoordinator];
NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Club"];
request.predicate = [NSPredicate predicateWithFormat:@"inRegion.name=%@", self.name];
NSError *error = nil;
NSArray * clubs = [ctxThread executeFetchRequest:request error:&error];
NSLog(@"[%@] Fetching map data. Club count is %d", self.name, [clubs count]);
int delayCounter = 0;
for(Club * club in clubs)
{
if(![club.hasCoord boolValue] && club != nil)
{
delayCounter++; // to deal with google maps api's DoS protection
[club setLongitudeAndLattitudeFromGoogle];
NSError * error;
if(![ctx save:&error])
NSLog(@"[%@] Problem saving region to database.", self.name);
}
if(delayCounter == 8)
{
[NSThread sleepForTimeInterval:(NSTimeInterval)2.0];
delayCounter = 0;
}
}
});
dispatch_release(MapFetchQ);
}
Когда вызываются эти сохранения, я получаю уведомление в главном потоке (в моем делегате приложения) примерно так:
- (void) contextDidSave: (NSNotification *) notification
{
NSManagedObjectContext * ctx = [self.clubsDB managedObjectContext];
[ctx mergeChangesFromContextDidSaveNotification:notification];
NSArray * updates = [[notification.object updatedObjects] allObjects];
for(Club * club in updates) // This never fires because updates never has objects
{
NSLog(@"*********** %@", club.name);
}
NSLog(@"[%@] %@", [self class], NSStringFromSelector(_cmd));
}
И я установил свой контроллер извлеченных результатов следующим образом (предикат верный, результаты ожидаемые с перезагрузкой приложения после передачи данных в хранилище):
-(void) setupFRC
{
NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Club"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:@"inRegion.name=%@ AND hasCoord=%@",[self.clubsDB regionTitleAsString], [NSNumber numberWithBool:YES]]; // Follow the relationshop and only display clubs from THIS region.
//request.predicate = [NSPredicate predicateWithFormat:@"inRegion.name=%@",[self.clubsDB regionTitleAsString]];
self.debug = YES;
self.fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.clubsDB.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
Есть какие-нибудь идеи относительно того, как я могу обновить соответствующий MOC, чтобы заставить выбранный контроллер результатов вести себя как нужно?