17

NSOperationを使用してデータをインポートするコードに取り組んでいます。NSManagedObjectインポート操作中に作成されたインスタンスをユーザーが元に戻せるようにしたいと考えています。

私が知るNSManagedObjectContext -undoManager限り、メイン スレッドから実行される操作に を使用することは不可能です。Use Thread Confinement to Support Concurrencyに関するCore Data Programming Guideセクションから、次の 2 つの条件があります。

  1. 管理対象オブジェクト コンテキスト間で (別のスレッドで) objectID のみを渡す必要があります。
  2. objectID を使用する前に、管理対象オブジェクトをコンテキストに保存する必要があります。

管理対象オブジェクトを共有する前に、プライベート ストレージ ( NSManagedObjectContext) からパブリック ストレージ ( )に移動する必要があるため、これは理にかなっています。NSPersistentStore

残念ながら、この-save:メッセージにより、元に戻すスタック内のマネージ オブジェクトも削除されます。同じガイドの「コア データを使用した メモリ管理」セクションから:

保留中の変更 (挿入、削除、または更新) がある管理対象オブジェクトは、そのコンテキストに save:、reset、rollback、または dealloc メッセージが送信されるか、変更を元に戻すための適切な回数の元に戻すまで、コンテキストによって保持されます。

この制限を回避するためにいくつかのことを試しましたが、最終的にはすべてがメイン スレッド (および回転するビーチ ボール) で発生する作業の大部分に戻ります。とても有難い。

--

拡張レーダーが送信されました: rdar://problem/8977725

4

5 に答える 5

2

この答えは、おそらく少し前後するでしょう。問題を正しく理解していれば、インポートを行っていますが、インポートが完了したら、ユーザーがインポートから保存されるものを選択できるようにしたいですか?

それが正しくない場合は、私の仮定を修正してください。この回答を更新します。

それが正しい場合、あなたができることは次のとおりです。

  1. 背景オブジェクトの作成を次のように変更します

    NSEntityDescription *myEntity = ... //Entity from your context
    [[NSManagedObject alloc] initWithEntity:myEntity
             insertIntoManagedObjectContext:nil];
    
  2. これらのエンティティを配列に格納します。
  3. 必要に応じて、エンティティをメイン スレッドに戻します。
  4. 保持したくないオブジェクトを解放します
  5. [myMainContext insertObject:managedObject]保持したいものを呼び出します。
  6. で保存を実行しますNSManagedObjectContext

これらのエンティティはまだ の一部ではないNSManagedObjectContextため、メモリ内にのみ存在し、まだ に関連付けられていないため、スレッド セーフである必要NSManagedObjectContextがあります。

もちろん、これは理論上のものであり、テストが必要です。ただし、それはあなたの目標を達成するはずです。

于 2011-02-10T07:44:31.823 に答える
0

1つのオプションは、インポートスレッドを永続化することです。スレッドのインポートが終了しても、アイドルループ状態になります。このようにして、スレッド化されたManagedObjectContextが適切なスレッドに保持されます。次に、ユーザーが変更を元に戻したい場合は、元にできるマネージャーを使用するようにスレッドにメッセージを送信します。

于 2011-02-09T14:19:37.033 に答える
0

これを検討したことがあり、既存の を使用したソリューションのみを探している可能性が非常に高いですが、念のためundoManager:

オブジェクトを挿入し、既存のものを更新しないため、各バッチがインポートされるときにトランザクション ID でタグ付けし、元に戻す場合にバックグラウンド スレッドで削除することができます。NSNumberタグには単純なインクリメントで十分です。

エレガントではありませんが、実行可能です。

于 2011-02-10T07:56:45.713 に答える
0

専門家ではありませんが、操作を実行するための 2 つ目のコンテキストを作成し、2 つのコンテキストをマージする必要があると思います。マージを元に戻すステップとして管理できるはずです。これは、ユーザーに関する限り、一連の操作全体を 1 つの元に戻すステップとして扱っている場合にのみ機能することに注意してください。

于 2011-02-09T03:20:03.273 に答える
0

バックグラウンド スレッドに別のコンテキストを使用し、それが完了したら[[backgroundContext undoManager] undo]、フォアグラウンド スレッドの取り消しスタックにプッシュするとします。私はそのようなことを試したことは一度もありませんが、頭のてっぺんから、それが機能しない理由が思いつきません。

于 2011-02-09T03:26:07.883 に答える