1

バックグラウンド GCD スレッドで Core Data に問題があります... レコードを更新したいのですが、取得して値を設定した後、更新されたレコードが実際に保存されないようです。

isUpdate初めて解析/保存を実行しているかどうか、または更新する必要があるレコードであるかどうかを教えてくれる設定済みの BOOL です。私の場合、レコードを更新しても、実際にはストアで更新されていないようです。

私は MagicalRecord ヘルパーを使用しています。これが私のコードです:

// Create background context
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init];
[backgroundContext setPersistentStoreCoordinator:[NSPersistentStoreCoordinator defaultStoreCoordinator]];
// Save the background context and handle the save notification
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(backgroundContextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:backgroundContext];

// Parsing data...
//..

Record *record;
if (!isUpdate) {
    record = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:backgroundContext];
} else {
    NSPredicate *recordPredicate = [NSPredicate predicateWithFormat:@"SELF.tag == %@", [[node attributeForName:@"tag"] stringValue]];
    record = [Record findFirstWithPredicate:recordPredicate];
}
[record setTitle:[[recordNode attributeForName:@"title"] stringValue]];

// Parsing other data...
//..

NSError *error = nil;
// save the context
[backgroundContext save:&error];
if (error) {
    NSLog(@"An error occurred: %@", error);
}

そして、ここに通知があります:

- (void)backgroundContextDidSave:(NSNotification *)notification {
    // Make sure we're on the main thread when updating the main context
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
                           withObject:notification
                        waitUntilDone:NO];
        return;
    }
    // merge in the changes to the main context on the main thread
    [[NSManagedObjectContext defaultContext] mergeChangesFromContextDidSaveNotification:notification];
}
4

2 に答える 2

2

あなたのコードは私にはかなり奇妙に聞こえます。

なぜNSManagedObjectContextDidSaveNotificationバックグラウンドスレッドに通知を登録するのですか?私は間違っているかもしれませんが、その通知をアプリの別の場所に登録する必要があります。

それを機能させたい場合は、その通知をメインスレッドに登録できます。たとえば、でそれを行うことができますAppDelegate

たとえば、didFinishLaunchingWithOptions:あなたができる方法で

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(backgroundContextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:backgroundContext];

次に、常に内でAppDelegate、変更を作成したメソッドとマージできます。

- (void)backgroundContextDidSave:(NSNotification *)notification {
    // Make sure we're on the main thread when updating the main context
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
                           withObject:notification
                        waitUntilDone:YES];
        return;
    }
    // merge in the changes to the main context on the main thread
    [[NSManagedObjectContext defaultContext] mergeChangesFromContextDidSaveNotification:notification];
}

コードは次の手順を実行します。

  1. まず、メインスレッドで実行しているかどうかを確認します。
  2. 登録する通知はメインスレッドとは異なるスレッドから発信される可能性があるため、メインスレッドでセレクターを実行する必要があります。
  3. 最後に、バックグラウンドで行った変更を含む通知とのマージを実行します。

完了すると、メインコンテキストが他のコンテキストで行われた変更で更新されていることがわかります。

編集

waitUntilDoneたぶん、 YESに変更することもできます。

それが役に立てば幸い。

于 2012-05-01T22:36:54.990 に答える
1

2 つのコンテキストを混合しています。このコードはおそらく悪いです:

 record = [Record findFirstWithPredicate:recordPredicate];

これは、あなたの backgroundContext ではなく、別のコンテキストでレコードを見つけると思います。次のように変更する必要があります。

 record = [Record findFirstWithPredicate:recordPredicate inManagedObjectContext:backgroundContext];
于 2012-05-02T14:06:07.640 に答える