0

最近、1つのストアのみを必要とする新しいアプリを開始しました(ドキュメントベースのアプリはありません)。しばらくの間、私は最終的にNSManagedObjectContextを回避できると思って非常に満足していました...バックグラウンドで保存したいと思うまで:-(

今、私は自分のコードについて混乱しています。例えば:

- (void)awakeFromInsert
{
    [super awakeFromInsert];
    [self resetCard];
    self.creationDate = TODAY;
    self.dictionary = [Dictionary activeDictionary];
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center postNotificationName:NOTE_NEWCARD object:self];    
}

[Dictionary activeDictionary]は、メインスレッドで作成されたNSManagedObjectへのポインターを返すNSManagedObject静的関数です。これにより、バックグラウンド保存中にクロス/コンテキストエラーが発生します。私のプログラムは常に同じストアから読み取るので、これを書くことは避けられると思いました。

[Dictionary activeDictionaryWithContext:...]

MagicalRecordを使用すると、常に同じバックエンドで作業している限り、コンテキストポインターの受け渡しを回避できると思います。そのコンテキストを取得するには、どの関数を使用する必要がありますか?

[NSManagedObjectContext MR_defaultContext]
[NSManagedObjectContext MR_context]
[NSManagedObjectContext MR_contextForCurrentThread]

この例では、オブジェクトは通知内で自分自身を送信します。これは、より多くの競合を引き起こすためにほぼ許可されたものです。

  • 通知の場合、常にobjectIDのみを送信する必要がありますか?

私のオブジェクトは、メインコンテキストで実行されている場合にのみ、副作用の操作/通知を発行する必要があるように思われます。ただし、これらの副次的な操作の一部は、オブジェクトグラフを変更して、他のエンティティの新しいインスタンスを作成します。

  • [MagicalRecord MR_saveAll]で保存した場合、前述の2つの問題のある関数呼び出しを安全に省略できますか?

  • 新しいバックグラウンド保存コンテキストのオブジェクトは、これらの追加の関数を呼び出さずに、メインスレッドのオブジェクトの正確なコピーになると想定する必要がありますか?

同じストアの同じオブジェクトに対してawakeFromInsertが複数回実行されるとは予想していなかったため、問題が発生しています。私はこのようなことを考えていました:

- (void)awakeFromInsert
{
    [super awakeFromInsert];
    if ([self managedObjectContext] == [NSManagedObjectContext MR_defaultContext]) {
        [self resetCard];
        self.creationDate = TODAY;
        self.dictionary = [Dictionary activeDictionary];
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center postNotificationName:NOTE_NEWCARD object:self];    
    }
}

これにより、awakeFromInsertコードが1回だけ実行されますが、バックグラウンド保存コンテキストでは実行されません。情報が失われるのではないかと心配しています

4

1 に答える 1

1

あなたは確かにその方法であなたのオブジェクトを通知で送ることができますが、私はそれに対してお勧めします。CoreDataに新しい親子コンテキストがあっても、NSManagedObjectsはスレッドセーフではないことを忘れないでください。オブジェクトを作成またはインポートする場合は、別のコンテキストで使用する前にオブジェクトを保存する必要があります。

MagicalRecordは、バックグラウンド保存用の比較的単純なAPIを提供します。

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext){
    MyEntity *newEntity = [MyEntity MR_createInContext:localContext];

    //perform other entity operations here
}];

このブロックは、NSManagedObjectContextを適切に設定することを心配することなく、すべての作業を実行します。

通知を介してNSManagedObjectsを渡してはならないもう1つの理由は、通知が受信されるスレッドがわからないことです。NSManagedObjectsはスレッドセーフではないため、これによりクラッシュが発生する可能性があります。

提示する通知アプローチのもう1つの代替方法は、NSManagedObjectContextDidSaveNotificationにオブザーバーを追加し、その通知で変更をマージすることです。これは、オブジェクトが保存された後にのみ発生し、親子関係または永続ストア(古い方法)のいずれかを介してコンテキストを横断するのに安全です。

于 2012-11-03T17:57:17.850 に答える