2つのスレッドからコアデータSQLデータベースにアクセスしているiOSアプリがあります。スレッドA(メインUIスレッド)はコアデータレコードを更新し、スレッドBはスレッドAが更新したばかりのエンティティコレクションからの読み取りを試みます。問題は、スレッドBがスレッドAが持続した変更を「認識」していないことです。
スレッドBは、NSOperationサブクラスオブジェクトをNSOperationQueueに追加することによって作成されます。NSOperationサブクラスのメインメソッドは次のようになります。
-(void) main {
// NEED to create the MOC here and pass to the methods.
NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[moc setUndoManager:nil];
[moc setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; // Had been working for months
[moc setPersistentStoreCoordinator:getApp().persistentStoreCoordinator];
[self doTheWorkWithMOC:moc]; // Actually performs updates, using moc
moc = nil;
}
後で、スレッドBはその変更を次のように保存します。
@try {
// register for the moc save notification - this is so that other MOCs can be told to merge the changes
[[NSNotificationCenter defaultCenter]
addObserver:getApp()
selector:@selector(handleDidSaveNotification:)
name:NSManagedObjectContextDidSaveNotification
object:moc];
NSError* error = nil;
if ([moc save:&error] == YES)
{
NSLog(@"%s SAVED FINE",__FUNCTION__);
}else {
NSLog(@"%s NOT saved, error=%@ %@",__FUNCTION__,error,[error localizedDescription]);
}
// unregister from notification
[[NSNotificationCenter defaultCenter]
removeObserver:getApp()
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
@catch (NSException * e) {
NSLog(@"%s Exception: %@",__FUNCTION__, e);
}
メインUIappdelegateには、保存通知を処理するための次のコードが含まれています。
- (void)handleDidSaveNotification:(NSNotification*) note
{
@try {
// Notifications run on the same thread as the notification caller.
// However, we need to ensure that any db merges run on the main ui thread.
// Hence:
[self performSelectorOnMainThread:@selector(mergeContexts:) withObject:note waitUntilDone:NO];
}
@catch (NSException * e) {
NSLog(@"appDelegate handleDidSaveNotification Exception: %@", e);
}
}
-(void)mergeContexts:(NSNotification*) note
{
if ([__managedObjectContext tryLock]==YES)
{
[__managedObjectContext mergeChangesFromContextDidSaveNotification:note];
[__managedObjectContext unlock];
}
}
ほとんどの場合、すべて正常に機能します。
ただし、スレッドAがデータベースを読み取るときにスレッドBによって書き込まれた変更が検出されないiPadが1つあります。
誰かが私のコードでこれを引き起こす何かを見ることができますか?
どうもありがとう