0

コア データ アプリケーションの一部のコードをコントローラーからモデルに移動中です。

定期的に行う特定のフェッチ要求に対して NSManagedObjectID を返すメソッドを作成しました。

+ (NSManagedObjectID*)teamProjectWithProjectId:(NSNumber *)projectId inContext:(NSManagedObjectContext*)context
{
    NSFetchRequest *teamRequest = [[NSFetchRequest alloc] initWithEntityName:@"TeamProject"];
    NSPredicate *teamPredicate = [NSPredicate predicateWithFormat:@"teamProjectId == %@",projectId];
    teamRequest.predicate = teamPredicate;
    TeamProject *teamProject = [[context executeFetchRequest:teamRequest error:nil] lastObject];
    if (teamProject)
    {
      return [teamProject objectID];
    }
    else
    {
      return nil;
    }
    return nil;
}

そして今、私がこれを行う方法を使用する必要がある場所ならどこでも:

NSManagedObjectID *teamProjectMoId = [TeamProject teamProjectWithProjectId:projectID];
TeamProject *currentProject = nil;
if (teamProjectMoId)
{
    currentProject = (TeamProject*)[self.managedObjectContext objectWithID:teamProjectMoId];
}

NSManagedObjectID はスレッド セーフですが、NSManagedObject はスレッド セーフではありません。そして、かなりの量のコードをコントローラー クラスからモデル カテゴリに移動できることをうれしく思います。

しかし、これでは十分ではありません。スレッドセーフを尊重する方法で、たった 1 行のコードで NSManagedObject にアクセスしたいと本当に思っています。私の理想は、次のようなものを書くことができることです:

TeamProject *currentProject = [TeamProject magicalMethodThatHandlesThreadSafety];

これは可能ですか?または、NSManagedObject のクリーンなアクセサ メソッドを作成するための戦略を持っている人はいますか?

4

1 に答える 1

1

バックグラウンドでルックアップを行う必要がある場所ならどこでも、一時的な MOC を作成できます。これは確かにスレッドに依存せず、ID を使用するよりも高速です (実際、MOC を作成すること自体が高速であるため、高速です)。

NSPrivateQueueConcurrencyTypeこれを行う 1 つの方法は、同時実行タイプを指定してメイン コンテキストに子を渡すことです。

+ (TeamProject*)teamProjectWithProjectId:(NSNumber *)projectId inContext:(NSManagedObjectContext*)context
{

    NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    temporaryContext.parentContext = context;

    NSFetchRequest *teamRequest = [[NSFetchRequest alloc] initWithEntityName:@"TeamProject"];
    NSPredicate *teamPredicate = [NSPredicate predicateWithFormat:@"teamProjectId == %@",projectId];
    teamRequest.predicate = teamPredicate;
    TeamProject *teamProject = [[temporaryContext executeFetchRequest:teamRequest error:nil] lastObject];

    return teamProject;
}

その他のシナリオとソリューションについては、この投稿もご覧ください。

編集:

わかりやすくするために、上記のメソッドは、返された MO を使用する同じスレッドから呼び出されることを意図しています。上記のアプローチの単なる「拡張」であり、ローカルで作成されたそのスレッド専用の MOC を使用してフェッチ操作をラップするため、安全に使用できます。

つまり、任意のスレッドから上記のメソッドを呼び出して、返された MO を同じスレッドで安全に使用できます。子 MOC を使用すると、一時的なプライベート MOC を作成することで、任意のスレッドでフェッチを実行できます。

別のスレッドで作成された MOC を参照して、現在のスレッドで子 MOC を作成しても安全です。

あるスレッドから別のスレッドに管理対象オブジェクトを渡すことが許可されていないことは依然として真実です。

于 2013-10-04T17:52:00.007 に答える