0

私はMagicalRecordを使用して、コアデータの保存とマルチスレッド化を支援しています。

GCDで新しいスレッドを開始します。その新しいスレッドで、エンティティが存在するかどうかを確認します。そうでない場合は、新しいものを作成して保存します。

saveUsingCurrentThreadContextWithBlock^(NSManagedObjectContext *localContext){}非メインスレッドで呼び出された場合、保存するためにメインスレッドに戻りますか?

または、コンテキストを新しいスレッドに渡す必要がありますか?

編集:

メインスレッドで、MBProgressインジケーターを作成し、新しいスレッドを作成します。

MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.mapView animated:YES];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

    Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username];

    if (person == NULL) {
        NSLog(@"SEPERATE THREAD | person %@ does not exist, creating", self.user.username);
        person = [Person MR_createEntity];
        person.name = self.user.username;
        person.uid = self.user.UID;

        [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) {
            [MBProgressHUD hideHUDForView:self.mapView animated:YES];

            Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username];

            if (person) {
                NSLog(@"COMPLETION BLOCK | person exists: %@", person.name);
            }
        }];
    }
    else {
        NSLog(@"SEPERATE THREAD | person %@ does", self.user.username);

            dispatch_async(dispatch_get_main_queue(), ^{
                [MBProgressHUD hideHUDForView:self.mapView animated:YES];
            });
    }
});

(この保存方法は永続性ではありません。アプリを再起動しましたが、Personエンティティが見つかりません):

2013-03-12 14:25:44.014  SEPERATE THREAD | person iDealer does not exist, creating
2013-03-12 14:25:44.014  SEPERATE THREAD | thread: <NSThread: 0x84ca720>{name = (null), num = 4}
2013-03-12 14:25:44.015  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Saving <NSManagedObjectContext (0x840ec30): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-03-12 14:25:44.015  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Save Parents? 0
2013-03-12 14:25:44.015  -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Save Synchronously? 0
2013-03-12 14:25:44.016  -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x840ec30) Context UNNAMED is about to save. Obtaining permanent IDs for new 1 inserted objects
2013-03-12 14:25:44.132  __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x840ec30) → Finished saving: <NSManagedObjectContext (0x840ec30): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-03-12 14:25:44.134  COMPLETION BLOCK | thread: <NSThread: 0x8435f30>{name = (null), num = 1}
2013-03-12 14:25:44.134  COMPLETION BLOCK | person exists: iDealer
4

3 に答える 3

7

わかりました、私はそれを働かせました:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username];

    if (person == NULL) {
            [MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext){
                Person *localPerson = [Person MR_createInContext:localContext];
                localPerson.name = self.user.username;

            } completion:^(BOOL success, NSError *error){
                [MBProgressHUD hideHUDForView:self.mapView animated:YES];
            }];
    }
    else {
        dispatch_async(dispatch_get_main_queue(), ^{
            [MBProgressHUD hideHUDForView:self.mapView animated:YES];
        });
    }
});

これは機能し、保存されます。この方法で casademora が何を意味するのかはわかりません。この方法を使用することと方法を使用することの違いを判断できませんsaveOnlySelf:completion:

コンテキストを永続ストアに保存できなかったようsaveOnlySelfです. 質問のコードで作成すると、コンテキストに配置されます。Person エンティティを検索すると、それを見つけることができました。しかし、アプリを終了して再起動すると、その Person エンティティは存在しません。スレッド コンテキストをメイン/デフォルト コンテキストに保存またはマージしているように感じましたが、そのコンテキストは保存されていませんでした。

編集:

MR をもう少しいじってみると、いずれかのsaveOnlySelfメソッドが非メイン スレッドで使用されると、ローカル コンテキストがデフォルト コンテキストにマージされますが、永続ストアには保存されないようです。完了後にデフォルトのコンテキストを確認すると、新しいエンティティが確かに存在します。しかし、アプリを終了して再実行すると、そこにはありません。

saveToPersistentStoreAndWaitコンテキストをマージしてストアに保存するには、タイプ メソッドの 1 つを呼び出す必要があります。

于 2013-03-12T20:29:58.643 に答える
2

MagicalRecord の現在のバージョンでは、はい、完了ブロックはメイン スレッドに戻ります。ただし、ここでの方法は正しくありません。save メソッドのより明示的なバリアントが追加されました。

saveOnlySelf:completion:
saveToPersistentStore:completion:

現在のバージョンでこれらのメソッドを見てください。また、与えられた localContext のマネージド オブジェクトのみを使用するようにしてください。その作業ブロックは任意のスレッド/キューで実行できますが、この場合でもコア データに適切なスレッド管理ルールを使用する必要があります。

于 2013-03-11T21:41:33.533 に答える
-1

はい、メインスレッドで実行する完了ブロック。例えば:

NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
[newQueue addOperationWithBlock:^{
    [MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext) {
        // save something
    } completion:^(BOOL success, NSError *error) {
        // this will execute in the main thread
    }];
}];
于 2013-03-11T21:41:21.643 に答える