2011-01-09 18 views
5

詳細ビューとテーブルビューを持つ標準分割ビューコントローラがあります。詳細ビューのボタンを押すと、オブジェクトがテーブルビューの順序で配置を変更することがあります。結果として生じる順序変更によってセクションが追加または削除されない限り、これは正常に機能します。私。オブジェクトはセクション内の順序を変更したり、セクション間を切り替えることができます。これらの注文変更は問題なく正しく機能します。しかし、オブジェクトがまだ存在しないセクションに移動しようとする場合、またはセクションを離れる最後のオブジェクトである場合(したがって、セクションの削除を必要とする)、アプリケーションがクラッシュします。"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が呼び出されることをどのようにして保証するのですか?

ありがとうございました!

答えて

1

この問題は、transient属性をsectionNameKeyPathとして使用することによって発生しています。代わりにsectionNameKeyPathに使用されている属性をデータベースに格納すると、問題は解決しました。 NSFetchedResultsControllerの内容に基づいてセクションを更新する方法があるかどうかは分かりません。一時的な属性をsectionNameKeyPathとして使用するときです。今のところ私は一時的な属性の制限を考慮しています。

+0

私のプロジェクトでは非常に似た問題が発生しています。 didChangeSectionは、想定されるときに呼び出されないようです。 sectionNameKeyPathに "objectID.URIRepresentation"を使用しています。これは、各オブジェクトをそれぞれのセクションに入れたいからです。私はiPhone 5.1シミュレータでテストしています。私のFRCは値に基づいてソートされます(減少から増加)ので、オブジェクトの値が変更されると、セクションの順序も変更されますが、didChangeSection関数は決して呼び出されません。なぜこれが起こっているのかについての直感はありますか?ありがとう。 – klyngbaek

+0

私もこれで苦労しました。最初にsectionNameKeyPathにnilを指定しました。すべてのオブジェクトが削除されたら、tableViewのデータソースメソッド(fetchedObjects == 0)のセクション数に対して0が返され、これがtableViewを破棄しました。この委譲メソッドを起動する必要がある場合は、何らかの種類のsectionNameKeyPathを指定する必要があります。これは今や明らかなようですが、私は木製のものとして私が分かち合うと思っていました。 – Schoob

+0

私は非常に似た問題を抱えていましたが、違いは一時的な属性を使用していましたが、私はデータモデルで属性を一切使用していませんでした。*私は、カスタムgetterとsetterを使って、すべての 'willAccess' ...' didChange'ものです。すべてが完璧に見えましたが、didChangeSectionは決して呼び出されませんでした。私のために解決したのは、最終的にそれを表現する一時的な属性を作成することでした。私は私のカスタムセッターを削除し、ちょうど私のカスタムゲッターを-primitiveValueForKey:を使用するように適応させることができました。 – Gobe

1

私はアプリケーションで同じことをしています(sectionNameKeyPathの一時的なプロパティ)、あなたが経験している問題を見ていません。私はこれをiOS 4.2.1でテストしています... iOS 3.XのFRCデリゲートコールバックを信頼できない既知のバグがあります.ControllerDidChangeContent:メッセージで完全な[tableView reloadData]を実行する必要があります。 see the FRC documentation

既存のセクションから別のエントリを持つ存在するセクションを、存在しないセクションだけでなく、行が1つしかないセクションから別の存在しないセクションにテストしました。

+0

ブレントを指摘してくれてありがとう。私はiOS 4.1を使用していますので、修正されているバグに直面している可能性が非常に高いです。 – robenk

+0

あなたはシミュレータでこれと同じ動作をしますか?あなたはそれ以降のバージョンを試しましたか? (私はこの機能に依存しているので、私は利己的な興味を持っています。顧客にバグを報告したくはありません;)悲しいことに、すべてのiDevicesを最新のものに更新しました。 –

+0

こんにちは、ブレント、元の問題が発見され、_only_シミュレータでテストされました。つまり、この問題が発生している間に実際のデバイスでアプリを試したことはありません。参考までに、SDKを4.2にアップグレードして一時的なプロパティを戻してしまったので、もはや問題は発生していません。これが4.1のSDKの問題であるという証拠です – robenk

関連する問題