0

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つあります。

誰かが私のコードでこれを引き起こす何かを見ることができますか?

どうもありがとう

4

1 に答える 1

0

ジャーニーマン、

まず、iOSv5およびLionで導入されたキューベースのMOCの使用に移行する必要があります。これにより、2つのMOCの同期を維持するのがはるかに簡単になります。ロックシステムを使用する必要がなくなります。

次に、キューに入れられたMOCに移動したら、「保存しました」通知に応答してそれらの同期を維持するのは非常に簡単です。

第三に、保存通知のオブザーバーを常に追加および削除するのはなぜですか?それはあなたにとって疑わしいと思いませんか?明らかに、MOC間の更新が欠落しています。

アンドリュー

于 2012-11-23T13:32:41.650 に答える