web-dev-qa-db-ja.com

新しいNSPrivateQueueConcurrencyTypeを介したコアデータのバックグラウンドフェッチ

IOS5では本当にとても簡単ですか?

私はAppDelegateで次のコードを使用してバックグラウンドフェッチを実行していました。

dispatch_queue_t downloadQueue = dispatch_queue_create("DownloadQueue", NULL);
dispatch_async(downloadQueue, ^{
        self.myDownloadClass = [[MyDownloadClass alloc]initInManagedObjectContext:self.managedObjectContext];
        [self.myDownloadClass download];
    });

dispatch_release(downloadQueue);

私のダウンロードクラスは、NSURLConnectionを実行して一部のXMLデータをフェッチし、NSXMLParserを使用してデータを解析してから、コアデータの複雑なスキーマを更新します。実際にコアデータを更新するには、常にメインスレッドに切り替えます。乱雑なコード、dispatch_sync(dispatch_get_main_queue()....への呼び出しが多い.

私の新しいコードは次のようになります。

NSManagedObjectContext *child = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[child setParentContext:self.managedObjectContext];

[child performBlock:^{
    self.myDownloadClass = [[MyDownloadClass alloc]initInManagedObjectContext:child];
    [self.myDownloadClass download];
    }];

親モデルオブジェクトのコンテキストタイプをNSMainQueueConcurrencyTypeに設定するために、AppDelegateの他のコードに小さな変更を加えました。

- (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}

それは非常にうまく機能しているようです。更新プロセス全体は引き続き別のスレッドで実行されますが、スレッドを作成する必要はありませんでした。魔法のようです。

物理コアデータファイルへの変更をコミットする場合は、親コンテキストでもsave:を呼び出す必要があることを覚えておいてください。

ここではあまり質問しませんでした。新しいiOS5マネージドオブジェクトコンテキストメソッドを検索したときに見つけたものはすべて、コード例なしで高レベルの詳細しか提供されなかったため、これを投稿しているので、他の人に役立ちます。バックグラウンドでコアデータをフェッチするための他のすべての検索は古く、時には非常に古くなります、iOS5より前にそれを行う方法について話し合います。

57
Paul Heller

はい-今では本当に簡単です(iOS5.0の場合)。 iOS 4との互換性については、以前のハードルが残っていますが、ドキュメントはスレッドの制限に関してそれほど悪くはありません。たぶん、これをwikiセクションに追加する必要がありますか?

2

この新しいAPIがどのように実装されているかを理解しようとしています。マルチスレッドコアデータの通常のパターンは次のようなものです。

通常はNSOperationですが、この例ではdispatch_asyncを使用して簡略化されています。

dispatch_queue_t coredata_queue; // some static queue

dispatch_async(coredata_queue, ^() {
    // get a new context for this thread, based on common persistent coordinator
    NSManagedObjectContext *context = [[MyModelSingleton model] threadedContext];

    // do something expensive

    NSError *error = nil;
    BOOL success = [context save:&error];
    if (!success) {
        // the usual.
    }

    // callback on mainthread using dispatch_get_main_queue();
});

次に、メインスレッドは、NSManagedObjectContextDidSaveNotificationに基づいてUIを更新し、メインコンテキストをマージすることで応答します。

新しいAPIは、このパターンのラッパーのようです。childコンテキストは、親から永続的なコーディネーターを取得して新しいコンテキストを作成するように見えます。また、initでNSPrivateQueueConcurrencyTypeを指定すると、performBlockパラメーターがプライベートキューで確実に実行されます。

新しいAPIは、入力するコードがはるかに少ないようには見えません。 「従来の」スレッドに勝る利点はありますか?

0
Joris Kluivers