尝试重新加载部分时出现断言失败错误
Posted
技术标签:
【中文标题】尝试重新加载部分时出现断言失败错误【英文标题】:Assertion failure error when trying to reload sections 【发布时间】:2015-11-19 08:10:09 【问题描述】:我正在使用TQMultistageTableView
库创建一个基于表的应用程序来扩展部分。我的要求是,如果用户将点击表格部分,则部分背景颜色应更改为蓝色,如果未选择/扩展,其余部分背景颜色应为白色。为此,我创建了一个数组来保存节索引,然后我正在重新加载此节。
第一次(当我的数组为零时),它工作正常。但问题是当我的数组中保存了一个部分索引(因为任何一个部分被展开/选择)然后我试图通过重新加载第二部分来扩展其他部分时,它会因以下错误而崩溃:
*** -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2935.137/UITableView.m:1368 中的断言失败
*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:无效 第 1 节中的行数。包含在第 1 节中的行数 更新后的现有节(0)必须等于 更新之前该部分中包含的行 (3),加号或减号 从该部分插入或删除的行数(0 插入, 0 已删除)加上或减去移入或移出的行数 该部分(0 移入,0 移出)。'
这是我的代码:
//头文件打开方法
- (void)mTableView:(TQMultistageTableView *)mTableView1 willOpenHeaderAtSection:(NSInteger)section
NSLog(@"Open Header ----%ld",section);
NSDictionary *selectedSection = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%ld", (long)section] ,@"section" ,nil];
for(int i=0;i<[ selectedArrayForSectionPlus count];i++)
if([[[selectedArrayForSectionPlus objectAtIndex:i] objectForKey:@"section"] isEqualToString:[NSString stringWithFormat:@"%ld", (long)section]])
[selectedArrayForSectionPlus removeObjectAtIndex:i];
[self.mTableView.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
return;
[selectedArrayForSectionPlus addObject:selectedSection];
[self.mTableView.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];//here it is crashing
//头部关闭方法
- (void)mTableView:(TQMultistageTableView *)mTableView willCloseHeaderAtSection:(NSInteger)section
NSLog(@"Close Header ---%ld",section);
for(int i=0;i<[ selectedArrayForSectionPlus count];i++)
if([[[selectedArrayForSectionPlus objectAtIndex:i] objectForKey:@"section"] isEqualToString:[NSString stringWithFormat:@"%ld", (long)section]])
[selectedArrayForSectionPlus removeObjectAtIndex:i];
[self.mTableView.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
return;
//viewForHeaderInSection 方法
- (UIView *)mTableView:(TQMultistageTableView *)mTableView viewForHeaderInSection:(NSInteger)section;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.mTableView.frame.size.width, 80)];
for (int i = 0; i<selectedArrayForSectionPlus.count; i++)
if([[[selectedArrayForSectionPlus objectAtIndex:i] objectForKey:@"section"] isEqualToString:[NSString stringWithFormat:@"%ld", (long)section]])
[view setBackgroundColor:[UIColor colorWithRed:0/255.0 green:150/255.0 blue:214/255.0 alpha:1.0]];
else
[view setBackgroundColor:[UIColor whiteColor]];
return view;
有人知道如何重新加载该部分吗?
感谢您的指点!
【问题讨论】:
【参考方案1】:在beginUpdates
和endUpdates
中封装您的部分重新加载调用,如下所示:
[self.mTableView.tableView beginUpdates];
[selectedArrayForSectionPlus removeObjectAtIndex:i];
[self.mTableView.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
[self.mTableView.tableView endUpdates];
编辑:与 OP 发表讨论。
-
点击第 1 部分呼叫
willOpenHeaderAtSection
。在此处跟踪点击的部分。
点击第 2 节呼叫 willCloseHeaderAtSection
。将部分与#1 中的跟踪部分匹配。如果匹配,请执行您的 willCloseHeaderAtSection
代码并重置跟踪部分。如果不匹配,则直接返回而不执行您的代码。
【讨论】:
@Abhinav感谢您的回复,我尝试使用 beginUpdates 和 endUpdates 重新加载部分,但仍然崩溃。 能否请您仔细检查包含行和节数据的模型对象。在每次 reload 调用之前,您需要确保您的模型包含正确的数据。 问题是假设如果我点击第二部分,那么“willOpenHeaderAtSection”只会调用,之后如果我再次点击第一部分,那么 1.“willCloseHeaderAtSection”和 2.“willOpenHeaderAtSection”正在打电话。 如果我在其他部分关闭时单击任何部分,我的代码工作正常。 知道了。你需要处理这个有点棘手的方式。由于您在调用willCloseHeaderAtSection
时正在删除对象,因此当您点击任何其他部分以展开它时,当 ios 触发对此方法的调用时,它会产生问题。您应该在willOpenHeaderAtSection
中跟踪当前打开/展开的单元格部分,并仅在部分匹配时才在willCloseHeaderAtSection
中执行您的代码,否则只需返回。如果匹配,则重置跟踪部分并在willCloseHeaderAtSection
中执行您的代码。我希望你明白我的意思。【参考方案2】:
当您重新加载特定部分时,其他部分数据源(您的数据数组)应与以前相同。
我认为您在重新加载部分调用之前更新了数据源。
这是您的问题
您不是在重新加载第 1 部分,而是在重新加载其他部分。在重新加载您的数据源(数据数组)之前,第 1 部分包含三行(记录),但是当您重新加载该部分时,由于某种原因,您的数据源(数据数组索引 1)更改为 0 行(记录)。数据源(数据数组)的索引 1 应包含三行。
在填充时检查您的数据源,并在更新前后进行比较。
【讨论】:
@M Zubair Shamshad 我检查了数据源,我的行数组完全不同。如果我在其他部分关闭时单击任何部分,它工作正常。唯一的问题是如果已经展开了一个部分并且我正在单击不同的部分。 我确信您的数据数组因某种原因而更改。崩溃报告与我所说的完全一样。 也有可能,因为它在 TQMultistageTableView 库的 openOrCloseHeaderWithSection 方法中崩溃,我没有办法解决这个问题。 好吧,让我们做一个测试...在numnerOfRowsInSection
方法中放置一个断点或nslog。并使用相同的崩溃场景比较第 1 节在重新加载节调用之前和之后的行数。
我在相同的场景中进行了测试,在第 1 节的行数为 4 之前,在 willOpenHeaderAtSection 方法的 reloadSections 之后..它直接崩溃而不调用 numberOfRowInSection 方法。【参考方案3】:
这是你的问题:
[self.mTableView.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
所以在使用此行之前添加[_mTableView reloadtable];
因为有一个标题和表格视图,如果你离开更新任何一个,我应该是问题。
如果您的问题在上述行中解决了,那就没问题....
【讨论】:
在重新加载该表的一部分之前,切勿直接重新加载整个表。【参考方案4】:当您打开第 1 节标题并在打开标题时更新标题时我遇到了同样的问题在不同的部分它用来抛出错误所以这就是我所做的工作正常 更新标题的代码
[self.mTableView.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
您还需要做的一件事是在 TQMultistageTableView.m 文件中的方法名称 -(void)openOrCloseHeaderWithSection:(NSInteger)section 只需粘贴以下代码即可完成
[self.tableView beginUpdates];
NSMutableArray *deleteIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
NSInteger oldSection = self.openedIndexPath.section;
NSInteger newSection = section;
if (oldSection <= -1)
if (oldSection != newSection)
insertIndexPaths = [self buildInsertRowWithSection:newSection];
else
if (oldSection != newSection && newSection > -1)
deleteIndexPaths = [self buildDeleteRowWithSection:oldSection];
insertIndexPaths = [self buildInsertRowWithSection:newSection];
else
deleteIndexPaths = [self buildDeleteRowWithSection:oldSection];
if ([deleteIndexPaths count] > 0)
[self.tableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
if ([insertIndexPaths count] > 0)
[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
【讨论】:
以上是关于尝试重新加载部分时出现断言失败错误的主要内容,如果未能解决你的问题,请参考以下文章