在我的應用程序我有一個UITableView
包含消息。每一行都是一條消息。當我刪除郵件時,我首先從消息數組中刪除它,然後用deleteRowsAtIndexPaths
:UITableView使用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)。
有沒有人遇到過這樣的問題?有沒有其他方法或解決方法可以阻止應用程序崩潰?
任何指針會很好
您需要確保'cellForRowAtIndexPath:'以及其他委託/數據源方法全部同步。手動刪除一行後,數據源返回的行數應該少一個。另外,保護對底層陣列的訪問。如果您的應用程序是多線程的,則可以使用同步塊或GCD以確保在主/前線程訪問它時後臺沒有任何內容正在修改您的底層結構。 –
所以更好的方法是使用GCD,並將deleteRowsAtIndexPaths:和reloadData方法放入隊列中,以免崩潰?這樣,如果應用程序仍在處理deleteRowsAtIndexPaths,則reloadData將一直等待,直到它完成第一次。 – Kex
是的 - 但不是將它們放入隊列中,而是總是在主隊列上執行這些操作可能更容易,也更明智。通常這些觸摸GUI的方法只會在主/ UI線程上運行(或者只是函數_properly_)。如果你有一個長時間運行的檢索數據的背景方法,當它使用更新後的值完成時,只需將dispatch_async'輸出到主線程。 –