2015-06-30 40 views
0

在我的應用程序我有一個UITableView包含消息。每一行都是一條消息。當我刪除郵件時,我首先從消息數組中刪除它,然後用deleteRowsAtIndexPathsUITableView使用deleteRowsAtIndexPaths但崩潰的應用程序,如果新行創建(競爭消息收到)

int index = (int)[self.messages indexOfObject:message]; 
    [self.messages removeObject:message]; 

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; 
    NSArray *indexes = [[NSArray alloc] initWithObjects:indexPath, nil]; 

    [self.tableView deleteRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft]; 

這是在接收到新消息然而,當正常工作時,push notification觸發表刷新。有時會在deleteRowsAtIndexPaths完成執行之前在數組中放置新消息,因此應用程序崩潰,因爲方法完成後表中的行數不等於之前的行數減去刪除的行數。例如錯誤消息:

終止應用程序由於未捕獲的異常「NSInternalInconsistencyException」,原因:「無效更新:在部分0無效 數量的行的更新後包含在 現有段中的行數( 3)必須等於該部分包含的 行數在更新之前(3),加或減 插入或刪除該行的行數(0插入, 1刪除)以及正數或負數的行移入或移出 該部分(移入0,移出0)。

有沒有人遇到過這樣的問題?有沒有其他方法或解決方法可以阻止應用程序崩潰?

任何指針會很好

+1

您需要確保'cellForRowAtIndexPath:'以及其他委託/數據源方法全部同步。手動刪除一行後,數據源返回的行數應該少一個。另外,保護對底層陣列的訪問。如果您的應用程序是多線程的,則可以使用同步塊或GCD以確保在主/前線程訪問它時後臺沒有任何內容正在修改您的底層結構。 –

+0

所以更好的方法是使用GCD,並將deleteRowsAtIndexPaths:和reloadData方法放入隊列中,以免崩潰?這樣,如果應用程序仍在處理deleteRowsAtIndexPaths,則reloadData將一直等待,直到它完成第一次。 – Kex

+0

是的 - 但不是將它們放入隊列中,而是總是在主隊列上執行這些操作可能更容易,也更明智。通常這些觸摸GUI的方法只會在主/ UI線程上運行(或者只是函數_properly_)。如果你有一個長時間運行的檢索數據的背景方法,當它使用更新後的值完成時,只需將dispatch_async'輸出到主線程。 –

回答

1

我有同樣的問題。而我所做的:

  1. 申報活動標誌更新:

    @property (nonatomic, assign) BOOL canEdit;

  2. 插入self.canEdit = NO當你執行一些更新操作

  3. 覆蓋willDisplayCell和檢查,如果有會顯示你的tableview數據源數組的最後一個單元格(所以,更新將在該單元格之後結束)

    -(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
    
    if ([dataArray count]- 1 == indexPath.row && self.canEdit == NO) 
           self.canEdit = YES;} 
    
  4. 當您收到推送通知時 - 檢查該標誌,如果是 - 執行更新。如果在一段時間後沒有請求更新

相關問題