關鍵信息:attempt to delete row 0 from section 0 which only contains 0 rows before the update
最近在處理刷新cell的時候有很小几率發送上面所報崩潰信息的問題,在網上找了一下信息包括騰訊bugly 分享的可能性,先貼出來看下:
解決方案
內部矛盾異常,斷言評估一個條件,如果條件爲 false ,調用當前線程的斷點句柄。每一個線程有它自已的斷點句柄,它是一個 NSAsserttionHandler 類的對象。當被調用時,斷言句柄打印一個錯誤信息,該條信息中包含了方法名、類名或函數名。然後,它就拋出一個 NSInternalInconsistencyException 異常。
NSInternalInconsistencyException,從它的字面意思來看的話,是不一致導致的,下面就一些例子
1. NSMutableDictionary的錯誤使用
比如把NSDictionary當做NSMutableDictionary來使用,從他們內部的機理來說,就會產生一些錯誤,NSMutableDictionary中有很多NSDictionary不支持的接口
[objc] view plain copy 在CODE上查看代碼片派生到我的代碼片
NSString *result = @"{\"username\”:\”aaa\”,\"phone\":\"15666666666\",\"bankcount\":\"98765432112345678\"}";
NSData *data = [result dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
if (info) {
NSString *username = [Utils UrlDecode: info[@"username"]];
[info setObject:username forKey:@"username"];
}
執行上述代碼後報錯:
[objc] view plain copy 在CODE上查看代碼片派生到我的代碼片
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
出錯原因在於:
[objc] view plain copy 在CODE上查看代碼片派生到我的代碼片
[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
返回的結果是immutable對象,不能直接對immutable進行賦值操作,否則會報錯。
修改後代碼:
[objc] view plain copy 在CODE上查看代碼片派生到我的代碼片
NSString *result = @"{\"username\”:\”aaa\”,\"phone\":\"15666666666\",\"bankcount\":\"98765432112345678\"}";
NSData *data = [result dataUsingEncoding:NSUTF8StringEncoding];
//----將immutable轉換爲mutable----
NSDictionary *temp = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSMutableDictionary *info = [NSMutableDictionary dictionaryWithDictionary:temp];
//----------------------
if (info) {
NSString *username = [Utils UrlDecode:info[@"username"]];
[info setObject:username forKey:@"username"];
}
2. 界面使用不當
[objc] view plain copy 在CODE上查看代碼片派生到我的代碼片
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
eason: 'Could not load NIB in bundle: 'NSBundle </var/mobile/Applications/74075F37-7B13-4D39-8686-050402501AE0/CanUSee.app> (loaded)' with name 'ViewController''
其中一個原因是:
在AppDelegate.m的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中使用xib文件初始化,但程序的入口是storyboard,didFinishLaunching不需要寫東西
self.viewController = [[ViewController alloc] initWithNibName: @"ViewController" bundle: nil];
工程裏面沒有ViewController.xib,初始化出錯。
3.Constant is not finite! That's illegal. constant:nan'
除數爲0時候崩潰
4. failed to obtain a cell from its dataSource
CellIdentifier I bet your cellForRowAtIndexPath is returning null.
應該避免cellForRowAtIndexPath 返回的cell爲空
5.對象爲nil,不存在
[MASViewConstraint setSecondViewAttribute:],nil調用約束方法導致崩潰
最終分析最符合情況的應該是3.4 這兩類。
在更新 TableView 的時候調用
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
crash掉了,報異常attempt to delete row 0 from section 0 which only contains 0 rows before the update。
原因:
在調用reloadRowsAtIndexPaths時,依賴於tableView先前的狀態已有要更新的cell,它內部是先刪除該cell,再重新創建,所以當你在原先沒有該cell的狀態下調用reloadRowsAtIndexPaths,會報異常你正在嘗試不存在的cell。
簡言之,如果你要改變tableView的cell數量,就不要調用更新局部的cell方法。
解決辦法
1.使用reloadData
reloadData是完全重新加載,包括cell數量也會重新計算,不會依賴之前tableView的狀態。
2.使用beginUpdates和 endUpdates(未自驗證,驗證者可留言)
當你在將要更改cell數量的時候都要通知tableView更新(調用[tableView beginUpdates];)
添加時通知使用方法(void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
移除時通知使用方法 (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
當你已經更改cell數量的時候都要告訴tableView更新完畢(調用[tableView endUpdates];)