2011-08-04 24 views
15

Tôi có một vanilla UITableView được quản lý bởi một NSFetchedResultsController để hiển thị tất cả các trường hợp của một thực thể Dữ liệu chính đã cho.tableView: cellForRowAtIndexPath được gọi với nil indexPath sau khi xóa mục

Khi người dùng xóa mục nhập trong chế độ xem bảng bằng cách vuốt qua nó, tableView:cellForRowAtIndexPath: cuối cùng được gọi trên số UITableViewController của tôi với số nilindexPath. Vì tôi đã không mong đợi nó sẽ được gọi với một nilindexPath, ứng dụng bị treo.

Tôi có thể khắc phục sự cố bằng cách kiểm tra giá trị nil và sau đó trả lại ô trống. Điều này dường như làm việc, nhưng tôi vẫn lo lắng rằng tôi có thể đã xử lý một cái gì đó sai trái. Bất kỳ ý tưởng? Có ai từng nhìn thấy tableView:cellForRowAtIndexPath: được gọi với số nilindexPath không?

Lưu ý rằng điều này chỉ xảy ra khi người dùng xóa từ chế độ xem bảng bằng cách vuốt qua ô. Khi xóa một mục bằng chế độ chỉnh sửa chế độ xem bảng, nó không xảy ra. Điều gì sẽ khác nhau giữa hai cách để xóa một ô?

Vì vậy, có thực sự là một tình huống OK để có được một nilindexPath trong một phương thức ủy nhiệm xem bảng?

Mã bộ điều khiển chế độ xem của tôi thực sự là tiêu chuẩn. Đây là việc xóa:

- (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> } 
} 

Điều này sẽ dẫn đến phương pháp NSFetchedResultsController đại biểu được gọi là:

- (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; 
    } 
} 

Và tất nhiên, các phương pháp nguồn dữ liệu được xử lý bởi các NSFetchedResultsController, ví dụ:

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

Rất cám ơn.

+1

Cậu xác minh tất cả những được gọi theo thứ tự dự đoán? – Mundi

+1

Hãy thử gọi 'reloadData' trên chế độ xem bảng của bạn trong' tableView: commitEditingStyle: forRowAtIndexPath' ngay lập tức * sau * lưu các thay đổi đối với bối cảnh đối tượng được quản lý. Tôi đã có một vấn đề tương tự với điều này và tải lại xem bảng cố định nó. – Greg

Trả lời

0

Tôi sẽ làm như thế này, vì bạn đang điền bảng trực tiếp từ ngữ cảnh được quản lý của bạn, tại sao không xóa đầu tiên xóa đối tượng khỏi bối cảnh được quản lý và sau đó cập nhật bảng ngay từ ngữ cảnh bằng cách sử dụng reloadData. Nhưng sử dụng cách tiếp cận của bạn tôi nghĩ rằng bạn cần phải thêm beginUpdatesendUpdates:

#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

Có vẻ như bạn đang xóa indexPath từ bảng nhưng nguồn bảng dữ liệu không được cập nhật. Bạn đã xác minh quá trình udation nguồn dữ liệu của NSFetchedResultsController có chính xác cập nhật nguồn dữ liệu bảng không?

-1

Tôi sử dụng CoreData trong chế độ xem bảng và cho phép người dùng xóa bản ghi và cập nhật chúng mọi lúc, tôi có chúng trong 4 ứng dụng mà không gặp sự cố bạn đã đề cập.

Tôi đã những FetchedResultsController Đại biểu Phương pháp trong mã của tôi

 - (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]; 

}

Các vấn đề liên quan