詳細ビューとテーブルビューを持つ標準分割ビューコントローラがあります。詳細ビューのボタンを押すと、オブジェクトがテーブルビューの順序で配置を変更することがあります。結果として生じる順序変更によってセクションが追加または削除されない限り、これは正常に機能します。私。オブジェクトはセクション内の順序を変更したり、セクション間を切り替えることができます。これらの注文変更は問題なく正しく機能します。しかし、オブジェクトがまだ存在しないセクションに移動しようとする場合、またはセクションを離れる最後のオブジェクトである場合(したがって、セクションの削除を必要とする)、アプリケーションがクラッシュします。"didChangeSection:" NSfetchedResultsControllerデリゲートメソッドが呼び出されていません
NSFetchedResultsControllerDelegateには、追加および削除されたセクションを処理するメソッドがあり、そのような場合に呼び出される必要があります。しかし、これらのデリゲートメソッドは何らかの理由で呼び出されていません。
問題のコードは、定型です:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"willChangeContent");
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
NSLog(@"didChangeSection");
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"didChangeObject");
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"didChangeContent");
[self.tableView endUpdates];
[detailViewController.reminderView update];
}
アプリケーションを起動し、次の出力でのセクションの結果を残すために最後のオブジェクト原因:あなたが見ることができるように
2011-01-08 23:40:18.910 Reminders[54647:207] willChangeContent
2011-01-08 23:40:18.912 Reminders[54647:207] didChangeObject
2011-01-08 23:40:18.914 Reminders[54647:207] didChangeContent
2011-01-08 23:40:18.915 Reminders[54647:207] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1145.66/UITableView.m:825
2011-01-08 23:40:18.917 Reminders[54647:207] Serious application error. Exception was caught during Core Data change processing: Invalid update: invalid number of sections. The number of sections contained in the table view after the update (5) must be equal to the number of sections contained in the table view before the update (6), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)
を、 "willChangeContent"、 "didChangeObject"(問題のオブジェクトの移動)、 "didChangeContent"がすべて正しく呼び出されました。 AppleのNSFetchedResultsControllerDelegateのドキュメントに基づいて、 "didChangeSection"は "didChangeObject"の前に呼び出されていて、クラッシュの原因となった例外を防ぐことができます。
私はdidChangeSectionが呼び出されることをどのようにして保証するのですか?
ありがとうございました!
私のプロジェクトでは非常に似た問題が発生しています。 didChangeSectionは、想定されるときに呼び出されないようです。 sectionNameKeyPathに "objectID.URIRepresentation"を使用しています。これは、各オブジェクトをそれぞれのセクションに入れたいからです。私はiPhone 5.1シミュレータでテストしています。私のFRCは値に基づいてソートされます(減少から増加)ので、オブジェクトの値が変更されると、セクションの順序も変更されますが、didChangeSection関数は決して呼び出されません。なぜこれが起こっているのかについての直感はありますか?ありがとう。 – klyngbaek
私もこれで苦労しました。最初にsectionNameKeyPathにnilを指定しました。すべてのオブジェクトが削除されたら、tableViewのデータソースメソッド(fetchedObjects == 0)のセクション数に対して0が返され、これがtableViewを破棄しました。この委譲メソッドを起動する必要がある場合は、何らかの種類のsectionNameKeyPathを指定する必要があります。これは今や明らかなようですが、私は木製のものとして私が分かち合うと思っていました。 – Schoob
私は非常に似た問題を抱えていましたが、違いは一時的な属性を使用していましたが、私はデータモデルで属性を一切使用していませんでした。*私は、カスタムgetterとsetterを使って、すべての 'willAccess' ...' didChange'ものです。すべてが完璧に見えましたが、didChangeSectionは決して呼び出されませんでした。私のために解決したのは、最終的にそれを表現する一時的な属性を作成することでした。私は私のカスタムセッターを削除し、ちょうど私のカスタムゲッターを-primitiveValueForKey:を使用するように適応させることができました。 – Gobe