iphone 検索 NSFetchedResultsControllerデリゲートとバックグラウンドで更新される更新




xcdatamodeld (2)

私の推測では、あなたのMOC did-save通知が送信れ、メインイベントスレッドの代わりにバックグラウンドスレッドで観察されています。 これにより、 NSFetchedResultsControllerDelegateがバックグラウンドスレッドでデリゲートメッセージを送信します。

did-save通知オブザーバが主スレッドに制御を渡すことを確認する必要があります。たとえば、次のようになります。

- (void)backgroundMOCDidSaveNotifiaction:(NSNotification *)notification
{
    [uiMOC performSelectorOnMainThread:
         @selector(mergeChangesFromContextDidSaveNotification:)
     withObject:notification waitUntilDone:NO];
}

私はゲスト管理アプリケーションを開発するNSFetchedResultsControllerの問題に出くわしました。

アプリケーションは基本的に(NSOperationサブクラスを使用して)バックグラウンドでゲストリストをダウンロードし、それらをマネージオブジェクトコンテキストに挿入し、UIスレッドのテーブルビューで表示します。

私はコアデータのマルチスレッドルールに従っていると思います(私はそのスレッド上で作成された操作のために別のMOCを持っています、私はメインのMOCをdid-save通知などを使って同期します)。

私が完全に理解していないのは、NSFetchedResultsControllerの振る舞いです。主なスレッドではなく、バックグラウンドスレッドでデリゲートメソッド(controllerDidChangeContentなど)を呼び出しているようです。

だから私の質問です - NSFetchedResultsControllerDelegateを使用してMOCから来た変更を観察するのは合法ですか?NSFetchedResultsControllerDelegateはメインスレッドで行われた変更だけで動作するように設計されていますか?

私の説明が十分にはっきりしているかどうかは分かりませんが、問題を示すためにコードを投稿することはできません。


免責事項

Daniel Dickisonの回答正しい答えです。 これらのステップのいくつかは自明ではないので、ここではいくつかの詳細と説明だけを提供しています。

2つの異なる管理対象オブジェクトコンテキストを使用することは正しいことです

UIスレッドMOC:

lazy var mainQueuemanagedObjectContext: NSManagedObjectContext = {
    let coordinator = self.persistentStoreCoordinator
    var managedObjectContext = NSManagedObjectContext(
        concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
    }()

輸送、ダウンロード、背景MOC:

lazy var transportManagedObjectContext:NSManagedObjectContext = {
    let coordinator = CoreDataStack.sharedInstance.persistentStoreCoordinator
    let managedObjectContext = NSManagedObjectContext(
        concurrencyType: .PrivateQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext

    }()

バックグラウンド操作にはバックグラウンドMOCを使用します。

(新しいデータがダウンロードされて保存されたなど)

transportManagedObjectContext.performBlockAndWait({ () -> Void in
    // ...add, change, delete objects, then save
    try transportManagedObjectContext.save()
})

アップルのドキュメントに従って、 Daniel Dickisonのバックグラウンド管理オブジェクトコンテキストへの応答を適用してください :

// Broadcast NSManagedObjectContextDidSaveNotification
NSNotificationCenter.defaultCenter().addObserver(
    self,
    selector: "mocDidSaveNotification:",
    name: NSManagedObjectContextDidSaveNotification,
    object: self.transportManagedObjectContext)

func mocDidSaveNotification(notification:NSNotification)
{
    mainQueuemanagedObjectContext.performSelectorOnMainThread(
        "mergeChangesFromContextDidSaveNotification:",
        withObject: notification,
        waitUntilDone: true)
}

注:私は、 performBlockAndWait()waitUntilDone: trueを使用する方が一般的です。 待機しないと競合条件が発生しないことを積極的に知ってなければwaitUntilDone: trueです。 私は、あなたが待たないと決めた場合、あなたのアプリケーションを徹底的にストレステストするようあなたにお勧めします。 私はバックグラウンドスレッドがUIを待つように自由を取るが、逆のことはしない

UIスレッドから聞く

NSFetchedResultsController MainQueueConcurrencyType Managed Object Contextを使用する必要があります。

let fetchedResultsController = NSFetchedResultsController(
    fetchRequest: fetchRequest,
    managedObjectContext: mainQueuemanagedObjectContext,
    sectionNameKeyPath: "yourKey",
    cacheName: nil)

NSFetchedResultsControllerは、バックグラウンドの管理オブジェクトコンテキストから解放され、マージが完了した後でcontrollerWillChangeContentdidChangeObjectなどを受け取ります。





background