マスター/詳細メカニズムを使用しています。テーブルビューコントローラーは、[controller:(NSFetchedResultsController *)controller didChangeObject:...]を使用して関連する行を更新します。挿入と削除でうまく機能します。
ここで、行を実際に削除するのではなく、単に「非表示」にします。
そこで、コアデータモデルにブール値の「deleted」を追加し、マスターは述語を使用して「deleted=FALSE」のみをフェッチします。
[controller:(NSFetchedResultsController *)controller didChangeObject:...]で、次のことを行う必要があります。
- NSFetchedResultsChangeUpdateを確認します。
- もしそうなら、私はおそらく「更新」する必要がありますle fetchedResultController(述語に一致するmanagedObjectがもう一致しないことを検出できるかどうかはわかりません)、
- テーブルビューから行を削除する必要があります。
コードは次のとおりです。
case NSFetchedResultsChangeUpdate:
// This is fired by saving managedObject.deleted from FALSE to TRUE
// ... so I would like to delete the corresponding row from the tableview
// without reloading the full table.
self.fetchedResultsController = nil;
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
しかし、それは期待どおりに機能せず、エラーメッセージでクラッシュします:
2012-05-31 09:48:23.293 TableViewTest[32701:fb03] CoreData: error:
``Serious application error.
An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.
Invalid update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update (7)
must be equal to the number of rows contained in that section before the update (7),
plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted)
and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
with userInfo (null)
メッセージは明確です。NSFetchedResultsControllerは正しいカウントを返しません。CoreDataリクエストログを有効にすることで、このメソッドでは変更がまだコミットされていないようです。
私は別の方法を試しました:
- NSFetchedResultsが実際にリクエストを行うことを確認してください(明示的にフェッチを呼び出し、キャッシュを削除します)。
- [fetchRequest includePendingChanges]を指定して、まだコミットされていない変更を含めようとしました
しかし、私はいつも同じ問題を抱えています。挿入と真の削除で機能するのはなぜですか(挿入と削除はコミットされませんが、NSFetchedResultsControllerによって表示されます)。
PS:この特定の問題を説明するために、Xcodeテンプレートから新しいプロジェクトを作成します(CoreData + MasterControllerオプションを使用)。githubhttps ://github.com/arnauddelattre/TableViewTestで見つけることができます。行を追加してから、行を選択して[論理的削除]をクリックしてみてください。
_
編集:Mundiの応答に続いて、Mundi は管理対象コンテキストでsaveメソッドを呼び出すように提案します。ご覧のとおり、私はすでに[controllerdidChangeObject]を呼び出すsaveメソッドを使用しています。したがって、保存で保存を呼び出すことになります。
私にとって奇妙なことは、それが機能しているように見えることです。しかし、私は起こりうる副作用を恐れています(saveでsaveを呼び出すため)。それは私が望むことを達成するための「標準的な」方法ですか?
そして、なぜこの動作が挿入/真の削除と異なるのか、私はまだ理解していません。