无效更新:第 0 节中的无效行数以 NSException 类型的未捕获异常终止
Posted
技术标签:
【中文标题】无效更新:第 0 节中的无效行数以 NSException 类型的未捕获异常终止【英文标题】:Invalid update: invalid number of rows in section 0 terminating with uncaught exception of type NSException 【发布时间】:2014-10-09 11:24:35 【问题描述】:我已阅读有关此的所有相关帖子,但仍然遇到错误:
'无效更新:第0节的行数无效。 更新 (5) 后包含在现有节中的行必须是 等于该节之前包含的行数 update (5),加上或减去插入或删除的行数 该部分(0 插入,1 删除)和加或减的数量 移入或移出该部分的行(0 移入,0 移出)。'
以下是详细信息:
我在打开单元格时使用代码打开钢琴表,它为子单元格提供每行有不同数量的单元格,它运行良好,但我需要修改一些东西,当我点击行时它打开然后如果我点击另一行我需要它来打开第二个并关闭第一个打开的行 这是我的代码 根视图.m
#pragma -mark TableViewDelegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 5;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
GCRetractableSectionController* sectionController = [self.retractableControllers objectAtIndex:section];
// NSLog(@"sectionController.numberOfRow %d",sectionController.numberOfRow );
return sectionController.numberOfRow;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
GCRetractableSectionController* sectionController = [self.retractableControllers objectAtIndex:indexPath.section];
return [sectionController cellForRow:indexPath.row];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
NSLog(@"index path section %d indexrow %d",indexPath.section ,indexPath.row);
GCRetractableSectionController* sectionController = [self.retractableControllers objectAtIndex:indexPath.section];
// vc.open = !vc.open;
// return [sectionController didSelectCellAtRow:indexPath.row];
if (indexPath.row == 1)
[myCustomView setHidden:YES];
NSLog(@"index path 11111 111111 1111111 indexrow %d",indexPath.row);
else if (indexPath.row == 2)
return [sectionController didSelectCellAtRow:indexPath.row];
// GCRetractableSectionController.m
#import "GCRetractableSectionController.h"
#import "RootViewController.h"
@interface GCRetractableSectionController ()
@property (nonatomic, assign) UIViewController *viewController;
- (void) setAccessoryViewOnCell:(UITableViewCell*) cell;
@end
@implementation GCRetractableSectionController
@synthesize useOnlyWhiteImages, titleTextColor, titleAlternativeTextColor;
@synthesize viewController;
@synthesize open, rowAnimation;
@synthesize backUp;
#pragma mark -
#pragma mark Initialisation
- (id) initWithViewController:(UIViewController*) givenViewController
if ((self = [super init]))
if (![givenViewController respondsToSelector:@selector(tableView)])
//The view controller MUST have a tableView proprety
[NSException raise:@"Wrong view controller"
format:@"The passed view controller to GCRetractableSectionController must respond to the tableView proprety"];
self.viewController = givenViewController;
// self.open = NO;
self.useOnlyWhiteImages = NO;
self.rowAnimation = UITableViewRowAnimationTop;
return self;
#pragma mark -
#pragma mark Getters
- (UITableView*) tableView
return [self.viewController performSelector:@selector(tableView)];
- (NSUInteger) numberOfRow
NSLog(@"the count %d",self.contentNumberOfRow);
return (self.open) ? self.contentNumberOfRow + 1 : 1;
- (NSUInteger) contentNumberOfRow
return 0;
- (NSString*) title
return NSLocalizedString(@"No title",);
- (NSString*) titleContentForRow:(NSUInteger) row
return NSLocalizedString(@"No title",);
#pragma mark -
#pragma mark Cells
- (UITableViewCell *) cellForRow:(NSUInteger)row
UITableViewCell* cell = nil;
if (row == 0) cell = [self titleCell];
else cell = [self contentCellForRow:row - 1];
return cell;
- (UITableViewCell *) titleCell
NSString* titleCellIdentifier = [NSStringFromClass([self class]) stringByAppendingString:@"title"];
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:titleCellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:titleCellIdentifier];
cell.textLabel.text = self.title;
if (self.contentNumberOfRow != 0)
cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%i items",), self.contentNumberOfRow];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[self setAccessoryViewOnCell:cell];
else
cell.detailTextLabel.text = NSLocalizedString(@"No item",);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryView = nil;
cell.textLabel.textColor = [UIColor blackColor];
return cell;
- (UITableViewCell *) contentCellForRow:(NSUInteger)row
NSString* contentCellIdentifier = [NSStringFromClass([self class]) stringByAppendingString:@"content"];
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:contentCellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:contentCellIdentifier] ;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [self titleContentForRow:row];
return cell;
- (void) setAccessoryViewOnCell:(UITableViewCell*) cell
NSString* path = nil;
if (self.open)
path = @"UpAccessory";
if (self.titleAlternativeTextColor == nil) cell.textLabel.textColor = [UIColor colorWithRed:0.191 green:0.264 blue:0.446 alpha:1.000];
else cell.textLabel.textColor = self.titleAlternativeTextColor;
else
path = @"DownAccessory";
cell.textLabel.textColor = (self.titleTextColor == nil ? [UIColor blackColor] : self.titleTextColor);
UIImage* accessoryImage = [UIImage imageNamed:path];
UIImage* whiteAccessoryImage = [UIImage imageNamed:[[path stringByDeletingPathExtension] stringByAppendingString:@"White"]];
UIImageView* imageView;
if (cell.accessoryView != nil)
imageView = (UIImageView*) cell.accessoryView;
imageView.image = (self.useOnlyWhiteImages ? whiteAccessoryImage : accessoryImage);
imageView.highlightedImage = whiteAccessoryImage;
else
imageView = [[UIImageView alloc] initWithImage:(self.useOnlyWhiteImages ? whiteAccessoryImage : accessoryImage)];
imageView.highlightedImage = whiteAccessoryImage;
cell.accessoryView = imageView;
#pragma mark -
#pragma mark Select Cell
- (void) didSelectCellAtRow:(NSUInteger)row
if (row == 0)
[self didSelectTitleCell];
else [self didSelectContentCellAtRow:row - 1];
- (void) didSelectTitleCell
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *myDecodedObject = [userDefaults objectForKey:@"tableViewDataPrevious"];
NSMutableArray *decodedArray =[NSKeyedUnarchiver unarchiveObjectWithData: myDecodedObject];
NSLog(@"the back Up Count %d",[decodedArray count]);
if ([decodedArray count]!=0)
NSLog(@"Back Up Array ");
NSLog(@"am here herer hererer hererer %@ " , decodedArray);
// it quit here
[self.tableView deleteRowsAtIndexPaths:decodedArray withRowAnimation:self.rowAnimation];
//
[self.tableView reloadData];
[self.tableView endUpdates];
// NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
// [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
NSLog(@"am here herer hererer hererer");
NSLog(@"didSelectedTitleCell");
self.open = !self.open;
NSLog(@"1");
if (self.contentNumberOfRow != 0) [self setAccessoryViewOnCell:[self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]]];
NSIndexPath* indexPath = [self.tableView indexPathForSelectedRow];
NSUInteger section = indexPath.section;
NSUInteger contentCount = self.contentNumberOfRow;
[self.tableView beginUpdates];
NSMutableArray* rowToInsert = [[NSMutableArray alloc] init];
for (NSUInteger i = 1; i < contentCount + 1; i++)
NSIndexPath* indexPathToInsert = [NSIndexPath indexPathForRow:i inSection:section];
[rowToInsert addObject:indexPathToInsert];
if (self.open)
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *myDecodedObject = [userDefaults objectForKey:@"tableViewDataPrevious"];
NSMutableArray *decodedArray =[NSKeyedUnarchiver unarchiveObjectWithData: myDecodedObject];
NSLog(@"the back Up Count %d",[decodedArray count]);
if ([decodedArray count]!=0)
NSLog(@"Back Up Array ");
[self.tableView deleteRowsAtIndexPaths:decodedArray withRowAnimation:self.rowAnimation];
//[self.tableView endUpdates];
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
[self.tableView insertRowsAtIndexPaths:rowToInsert withRowAnimation:self.rowAnimation];
[self.tableView endUpdates];
backUp = [[NSMutableArray alloc]init];
[backUp addObjectsFromArray:rowToInsert];
NSLog(@"the back Up Count %@", backUp );
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:backUp];
[userDefaults setObject:myEncodedObject forKey:@"tableViewDataPrevious"];
;
[userDefaults synchronize];
else
[self.tableView deleteRowsAtIndexPaths:rowToInsert withRowAnimation:self.rowAnimation];
[self.tableView endUpdates];
[self.tableView endUpdates];
if (self.open) [self.tableView scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionTop animated:YES];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
- (void) didSelectContentCellAtRow:(NSUInteger)row
@end
输出是
2014-10-09 13:10:13.747 Brnlysta2[10199:90b] the back Up Count (
"<NSIndexPath: 0x8e8fb80> length = 2, path = 0 - 1",
"<NSIndexPath: 0x8e87900> length = 2, path = 0 - 2",
"<NSIndexPath: 0x8e871c0> length = 2, path = 0 - 3",
"<NSIndexPath: 0x8e908e0> length = 2, path = 0 - 4"
)
2014-10-09 13:10:14.717 Brnlysta2[10199:90b] index path section 1 indexrow 0
2014-10-09 13:10:14.718 Brnlysta2[10199:90b] the back Up Count 4
2014-10-09 13:10:14.718 Brnlysta2[10199:90b] Back Up Array
2014-10-09 13:10:14.719 Brnlysta2[10199:90b] am here herer hererer hererer (
"<NSIndexPath: 0x8b3bb60> length = 2, path = 0 - 1",
"<NSIndexPath: 0x8b8e5c0> length = 2, path = 0 - 2",
"<NSIndexPath: 0x8b75f60> length = 2, path = 0 - 3",
"<NSIndexPath: 0x8b7b960> length = 2, path = 0 - 4"
)
2014-10-09 13:10:14.719 Brnlysta2[10199:90b] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2935.137/UITableView.m:1368
2014-10-09 13:10:14.722 Brnlysta2[10199:90b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (5) must be equal to the number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (0 inserted, 4 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(
0 CoreFoundation 0x017fe1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0157d8e5 objc_exception_throw + 44
2 CoreFoundation 0x017fe048 +[NSException raise:format:arguments:] + 136
3 Foundation 0x0115d4de -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4 UIKit 0x00315f63 -[UITableView _endCellAnimationsWithContext:] + 13402
5 UIKit 0x00326590 -[UITableView _updateRowsAtIndexPaths:updateAction:withRowAnimation:] + 337
6 UIKit 0x0032660b -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 55
7 Brnlysta2 0x0000368e -[GCRetractableSectionController didSelectTitleCell] + 382
8 Brnlysta2 0x000034d7 -[GCRetractableSectionController didSelectCellAtRow:] + 71
9 Brnlysta2 0x00008f13 -[RootViewController tableView:didSelectRowAtIndexPath:] + 531
10 UIKit 0x003279a1 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1513
11 UIKit 0x00327b14 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 279
12 UIKit 0x0032c10e __38-[UITableView touchesEnded:withEvent:]_block_invoke + 43
13 UIKit 0x0025b0aa ___afterCACommitHandler_block_invoke + 15
14 UIKit 0x0025b055 _applyBlockToCFArrayCopiedToStack + 403
15 UIKit 0x0025ae76 _afterCACommitHandler + 532
16 CoreFoundation 0x017c636e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
17 CoreFoundation 0x017c62bf __CFRunLoopDoObservers + 399
18 CoreFoundation 0x017a4254 __CFRunLoopRun + 1076
19 CoreFoundation 0x017a39d3 CFRunLoopRunSpecific + 467
20 CoreFoundation 0x017a37eb CFRunLoopRunInMode + 123
21 GraphicsServices 0x037a25ee GSEventRunModal + 192
22 GraphicsServices 0x037a242b GSEventRun + 104
23 UIKit 0x0023df9b UIApplicationMain + 1225
24 Brnlysta2 0x0000669d main + 141
25 libdyld.dylib 0x01e43725 start + 0
)
libc++abi.dylib: terminating with uncaught exception of type NSException
【问题讨论】:
【参考方案1】:当你做一些编辑/更新 UITableView 的事情时,它会检查一些 dataSource 方法是否仍然存在数据完整性。你有一个问题。在您的 numberOfSectionsInTableView
或 tableView: numberOfRowsInSection:
方法上,存在计算错误。在调用 deleteRowsAtIndexPaths 之前,还需要更新用于计算节/行计数的必要属性。
顺便说一句,在 deleteRowsAtIndexPaths 之后使用 reloadData 没有任何意义。它可能会干扰您的删除动画。
【讨论】:
我们不能不看 numberOfSectionsInTableView 和 tableView: numberOfRowsInSection: 方法。 好的,它太长了,我对行使用多个对象,每个控制器返回其行部分的行数 但是假设我有 4 个部分,我有 4 个 roes,2 个有 6 行,3 个有 6 行,4 是空的 然后在调用 deleteRowsAtIndexPaths 之前,更新这些对象,以便它们在删除后返回正确的行数。 好吧,没有看到源代码真的很难理解。我看到的主要问题是您的 tableview 数据结构不合理。以上是关于无效更新:第 0 节中的无效行数以 NSException 类型的未捕获异常终止的主要内容,如果未能解决你的问题,请参考以下文章
NSInternalInconsistencyException(无效更新:第 0 节中的行数无效)
tableView 编辑委托方法不起作用(无效更新:第 0 节中的行数无效)
无效更新:第 0 节中的无效行数。更新后现有节中包含的行数 (3)
iOS 8:从 NSFetchedResultsController 的委托中捕获异常,无效更新:第 0 节中的行数无效
应用程序崩溃:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第 0 节中的行数无效