2011-08-04 6 views
15

UITableViewは、NSFetchedResultsControllerによって管理されていますが、特定のCore Dataエンティティのすべてのインスタンスを表示します。tableView:アイテムを削除した後にnil indexPathを指定してcellForRowAtIndexPathを呼び出す

ユーザーがテーブルビューの項目をスワイプして削除すると、最終的にUITableViewControllertableView:cellForRowAtIndexPath:が呼び出され、nilindexPathと表示されます。私はそれがnilindexPathと呼ばれることを期待していなかったので、アプリがクラッシュします。

値がnilであることを確認して空のセルを返すことで、クラッシュを回避できます。これはうまくいくようですが、私はまだ何か問題を処理している可能性があることを心配しています。何か案は?誰もがnilindexPathと呼ばれるtableView:cellForRowAtIndexPath:を見たことがありますか?

これは、ユーザーがセルをスワイプしてテーブルビューから削除した場合にのみ発生することに注意してください。テーブルビュー編集モードを使用してアイテムを削除すると、そのアイテムは削除されません。セルを削除する2つの方法の違いは何ですか?

テーブルビューデリゲートメソッドでnilindexPathを取得するのは本当に問題ありませんか?

私のビューコントローラのコードは本当に標準です。ここでの削除は以下のとおりです。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     // Delete the row from the data source 
     NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
     [self.moc deleteObject:managedObject]; 
     NSError *error = NULL; 
     Boolean success = [self.moc save:&error]; 
     if (!success) { <snip> } 
     // actual row deletion from table view will be handle from Fetched Result Controller delegate 
     // [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } else { <snip> } 
} 

これが呼び出されNSFetchedResultsControllerデリゲートメソッドにつながる:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
    atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
    newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    UITableView *tableView = self.tableView; 
    switch(type) { 

     case NSFetchedResultsChangeDelete: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

     case NSFetchedResultsChangeInsert: <snip> break; 
     case NSFetchedResultsChangeUpdate: <snip> break; 
     case NSFetchedResultsChangeMove: <snip> break; 
    } 
} 

そしてもちろん、データソースメソッドはNSFetchedResultsControllerによって処理され、例えば:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; 
    return [sectionInfo numberOfObjects]; 
} 

多くのありがとうございます。

+1

をこれらFetchedResultsControllerデリゲートメソッドを持っていますか? – Mundi

+1

'tableView:commitEditingStyle:forRowAtIndexPath'のテーブルビューで' reloadData'を呼び出すことをお勧めします。私はこれと同様の問題を抱えていて、それを固定したテーブルビューを再読み込みしました。 – Greg

答えて

0

管理されたコンテキストからテーブルを直接取り込んでいるので、削除しないとまず管理されたコンテキストからオブジェクトを削除してから、reloadDataを使用してコンテキストからテーブルを即座に更新します。しかし、あなたのアプローチを使用して私はあなたがbeginUpdatesendUpdatesを追加する必要があると思う:あなたは、テーブルが、テーブルのデータソースが更新されていないからindexPathを削除するよう

#pragma mark - 
#pragma mark Fetched results controller delegate 


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
[self.tableView beginUpdates]; 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
     atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 

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 { 

UITableView *tableViews = self.tableView; 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     [tableViews insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     [tableViews deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     [_delegate configureCell:[tableViews cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
     break; 

    case NSFetchedResultsChangeMove: 
     [tableViews deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     [tableViews insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    [self.tableView endUpdates]; 
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 
    [self.tableView scrollToRowAtIndexPath:indexPath 
         atScrollPosition:UITableViewScrollPositionMiddle 
           animated:NO]; 
} 
2

それはそうです。 NSFetchedResultsControllerによるデータソースのudationプロセスがテーブルのデータソースを正しく更新していることを確認しましたか?

-1

私はCoreDataをテーブルビューで使用し、ユーザーがレコードを削除して常に更新できるようにしていますが、私が4つのアプリケーションで問題が発生することなくそれらを持っています。

私はあなたがこれらすべてが予測ために呼び出されます確認しました私のコードで

 - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates. 
    [self.myTableView beginUpdates]; 
} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
     [self.myTableView endUpdates]; 

}

関連する問題