我在UITableView中顯示插入,更新和刪除的數組對象,偶爾我會得到下面的異常,即使我正在小心處理更改。我在GitHub上有完整的代碼示例。與UITableView崩潰
https://github.com/brennanMKE/TableMaddness
此示例項目使用它們實現NSCoding和NSCopying還有的isEqual對象,以便更新與插入,更新和刪除該表可以模擬一下我在這是有同樣的問題一個真正的應用程序正在做。我正在避免使用使用NSFetchedResultsController的Core Data,所以我想知道如果我沒有使用Core Data,我應該使用它。在
斷言故障 - [UITableView的_endCellAnimationsWithContext:],/SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:1330 2013年11月25日14:43:20.217 TableMaddness [13411:70B]終止應用程序由於未捕獲異常'NSInternalInconsistencyException',原因:'無效更新:第0節中的行數無效。更新(4)後現有節中包含的行數必須等於更新前該節中包含的行數(4)加上或減去從該部分插入或刪除的行數(插入1個,刪除0個)並加上或減去移入或移出該部分的行數(移入0,移出0)。
下面是相關的代碼。
// determine items which need to be inserted, updated or removed
NSMutableArray *inserts = [@[] mutableCopy];
NSMutableArray *deletes = [@[] mutableCopy];
NSMutableArray *reloads = [@[] mutableCopy];
// look for inserts
for (NSUInteger row=0; row<fetchedItems.count; row++) {
SSTItem *item = fetchedItems[row];
if (![self.currentItems containsObject:item]) {
// inserts are items which are not already in self.items
[inserts addObject:[NSIndexPath indexPathForRow:row inSection:0]];
}
else {
NSUInteger otherIndex = [self.currentItems indexOfObject:item];
SSTItem *otherItem = [self.currentItems objectAtIndex:otherIndex];
if (![item.modified isEqualToDate:otherItem.modified]) {
[reloads addObject:[NSIndexPath indexPathForRow:row inSection:0]];
}
}
}
// look for deletes
for (NSUInteger row=0; row<self.currentItems.count; row++) {
SSTItem *item = self.currentItems[row];
if (![fetchedItems containsObject:item]) {
[deletes addObject:[NSIndexPath indexPathForRow:row inSection:0]];
}
}
static NSString *lock = @"LOCK";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (kDelay/4) * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
// lock is required to prevent inconsistencies when changing view orientation during rotation
@synchronized(lock) {
self.currentItems = fetchedItems;
NSUInteger numberOfRowsInSection = [self tableView:self.tableView numberOfRowsInSection:0];
DebugLog(@"numberOfRowsInSection: %li", numberOfRowsInSection);
DebugLog(@"self.items: %li", self.currentItems.count);
MAAssert(self.currentItems.count == numberOfRowsInSection, @"Match is required");
if (inserts.count || deletes.count || reloads.count) {
[self.tableView beginUpdates];
#ifndef NDEBUG
for (NSIndexPath *indexPath in inserts) {
DebugLog(@"Inserting at %li", (long)indexPath.row);
}
for (NSIndexPath *indexPath in deletes) {
DebugLog(@"Deleting at %li", (long)indexPath.row);
}
for (NSIndexPath *indexPath in reloads) {
DebugLog(@"Reloading at %li", (long)indexPath.row);
}
#endif
[self.tableView insertRowsAtIndexPaths:inserts withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView deleteRowsAtIndexPaths:deletes withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadRowsAtIndexPaths:reloads withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
}
index++;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kDelay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self runNextUpdate];
});
});
在調用'beginUpdates'並執行表更改之前,需要更新表的數據源以反映新的行集。 – rmaddy
@rmaddy此代碼將self.currentItems設置爲fetchedItems在synchronized塊中。我在下面選擇的答案可以防止異常,但我認爲同步塊可以防止這個問題。至少現在我知道這個問題是由於一次運行多個更新引起的。 – Brennan