2

この質問に対する答えを見つけようとしましたが、ドキュメントからもStackOverflowからも質問を見つけることができませんでした。すでにこのような質問がある場合は、見つからなかったので、万が一の解決策として大歓迎です。

私の状況は次のとおりです。ユーザーと運転免許証の2つのコアデータエンティティがあります。

User  <--- 1 to 1 ---> Driving Licence

コアデータ操作の抽象化レイヤーとしてMagicalRecordを使用しています。

私のUserクラス(NSManagedObjectから派生)は2つのメソッドを公開しています。

ユーザーのシングルトンインスタンスにアクセスするための1つ(アプリ全体で使用される唯一のインスタンス):

+ (User *)currentUser {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if ([User MR_findFirst] == nil) {

            User *user = [User MR_createEntity];
            user.drivingLicence = [DrivingLicence MR_createEntity];
            [[user managedObjectContext] MR_save];
        }
    });

    return [User MR_findFirst];
}

また、ユーザーデータ(NSManagedObjectから派生)をリセットするために使用されるメソッド:

- (void)resetFields
{
   self.name = nil;
   self.surname = nil;
   ....
   [self.drivingLicence MR_deleteEntity];
   self.drivingLicence = [DrivingLicence MR_createEntity];
   [self.managedObjectContext MR_save];
}

時々、私はかなりランダムに言うでしょう、drivingLicenceフィールドはたまたまnullです。resetFieldsメソッドがバックグラウンドスレッドによって呼び出される場合があります。

他のコンテキストとのマージのために、一連の命令である可能性があります

   [self.drivingLicence MR_deleteEntity];
   self.drivingLicence = [DrivingLicence MR_createEntity];

混乱を招き、drivingLicenceが最後に削除される可能性がありますか?または、この予期しないnull値の理由は他に何でしょうか?

4

2 に答える 2

2

MR_createEntityを使用する場合、[NSManagedObjectContext MR_defaultContext]を介してアクセスされる、デフォルトのコンテキストを暗黙的に使用しています。あなたが絶対にポジティブでない限り、これを行うことは非常に危険です。あなたはそれをメインスレッドから呼んでいます。あなたの例では、すべてがメインスレッドから呼び出され、 self.managedObjectContextインスタンス変数もデフォルトのコンテキストを指している場合、これはすべて正しく機能するはずです。それ以外の場合は、使用しているコンテキストについて明示的にする必要があります。MagicalRecordは、コンテキストが機能する必要があるすべてのメソッドの最後にinContext:オプションのパラメーターを設定することにより、これらの規則を提供します。MR_createInContext メソッドを確認し、コンテキストの使用法を明示してください

于 2012-11-13T17:27:12.997 に答える
0

この問題にぶつかるだけです。私たちの発見に基づいて、上記のcasademoraの回答にコメントを追加したいと思います。

コアデータやその他のメソッドはスレッドセーフではないことを覚えておくことが重要です。MR_saveこの問題を回避するために、MagicalRecordアクションをキューに委任します。MR_saveToPersistentStoreAndWait特に、複数のスレッドで同時に保存アクション(など)を実行しないように注意することが重要です。

ただし、、、およびメインスレッド間の接続はより微妙ですMR_createEntity。MagicalRecordバージョン2.3.xの時点では、引数がない場合、デフォルトで。になるとは思いません。デフォルトはになっていると思います。 メインスレッドにある場合はデフォルトのコンテキストを返しますが、そうでない場合は返しません。元のポスターが上に表示されているもの(失われたデータ)を簡単に確認できるため、結果を理解していない場合、これは危険です。MR_defaultContextMR_createEntityMR_defaultContextMR_contextForCurrentThreadMR_contextForCurrentThread

実際、このメモは、を使用する際の問題でMR_createEntityInContext:localContextはなく、を使用する必要があることを示しています。MR_createEntityMR_contextForCurrentThreadGCD

を使用するロジックについては、githubの関数定義を参照してください。MR_createEntityMR_contextForCurrentThread

于 2016-05-21T23:46:27.123 に答える