Ios insertRowsAtIndexPaths:带有ScrollToRowatineXpath:会导致UITableView节被错误隐藏
我创建了一个UITableview,其中包含可单击的部分。当你点击它们时Ios insertRowsAtIndexPaths:带有ScrollToRowatineXpath:会导致UITableView节被错误隐藏,ios,cocoa-touch,uitableview,uikit,Ios,Cocoa Touch,Uitableview,Uikit,我创建了一个UITableview,其中包含可单击的部分。当你点击它们时 它们“扩展”以显示其中的细胞 单击的部分将滚动到视图的顶部 我计算所有IndExpath以插入/删除必要的单元格,然后使用以下代码插入它们: [self.tableView beginUpdates]; [self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation]; [self.tableView deleteRow
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation];
[self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
只有一个问题-选定部分下面的部分被隐藏。第一个屏幕截图显示了tableview的外观。第二个屏幕截图显示了它的实际外观
如果向上滚动(使隐藏部分在屏幕外),然后向下滚动,则隐藏部分将返回(再次可见)。我对发生这种情况的原因的猜测如下:
插入/删除动画与ScrollToRowatineXpath同时发生,这会混淆TableView。如果我没有做ScrollToRowatineXpath
3和4部分,那么它们可能已经脱离了屏幕,因此tableView仍然认为它们脱离了屏幕。UITableview作为优化隐藏屏幕外的单元格/分区。如果我在之后用dispatch\u调用scrollToRowatinedexpath
并持续2秒,则第3节和第4节将正确显示
所以我想我知道为什么会发生这种情况,但我不知道如何修复/覆盖这个UITableview优化。实际上,如果我实现了ScrollViewDiEndScrollingAnimation
,然后在此函数中添加一个断点,应用程序将正确显示第3节和第4节(这就是我获得第一个屏幕截图的原因)。但是一旦继续进行这个功能,细胞就会消失
完整的项目可以下载
其他实现详细信息:节是合法的UITableView节。我添加了一个TapGestureRecognitor,它触发对tableview的委托回调。下面是打开这些部分的整个方法
- (void)sectionHeaderView:(SectionHeaderView *)sectionHeaderView sectionOpened:(NSInteger)sectionOpened
{
// Open
sectionHeaderView.numRows = DefaultNumRows;
sectionHeaderView.selected = YES;
NSMutableArray *pathsToOpen = [[NSMutableArray alloc] init];
for (int i = 0; i < sectionHeaderView.numRows; i++)
{
NSIndexPath *pathToOpen = [NSIndexPath indexPathForRow:i inSection:sectionOpened];
[pathsToOpen addObject:pathToOpen];
}
// Close
NSMutableArray *pathsToClose = [[NSMutableArray alloc] init];
if (openSectionHeader)
{
for (int i = 0; i < openSectionHeader.numRows; i++)
{
NSIndexPath *pathToClose = [NSIndexPath indexPathForRow:i inSection:openSectionHeader.section];
[pathsToClose addObject:pathToClose];
}
}
// Set Correct Animation if section's already open
UITableViewRowAnimation insertAnimation = UITableViewRowAnimationBottom;
UITableViewRowAnimation deleteAnimation = UITableViewRowAnimationTop;
if (!openSectionHeader || sectionOpened < openSectionHeader.section)
{
insertAnimation = UITableViewRowAnimationTop;
deleteAnimation = UITableViewRowAnimationBottom;
}
openSectionHeader.numRows = 0;
openSectionHeader.selected = NO;
openSectionHeader = sectionHeaderView;
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation];
[self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
-(无效)sectionHeaderView:(sectionHeaderView*)sectionHeaderView SectionOpen:(NSInteger)SectionOpen
{
//打开
sectionHeaderView.numRows=默认numRows;
sectionHeaderView.selected=是;
NSMUTABLEARRY*pathsToOpen=[[NSMUTABLEARRY alloc]init];
对于(int i=0;i
据我所知,返回已使用的剖面视图时会出现问题。而不是:
- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section
{
return [self.sectionHeaderViews objectAtIndex:section];
}
如果每次都创建一个新视图,我不会有任何问题:
- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section{
SectionHeaderView *sectionHeaderView = [self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView_NibName];
sectionHeaderView.textLabel.text = [NSString stringWithFormat:@"Section %d", section];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:sectionHeaderView action:@selector(handleTap:)];
[sectionHeaderView addGestureRecognizer:tapRecognizer];
sectionHeaderView.section = section;
sectionHeaderView.delegate = self;
return sectionHeaderView;
}
这可能是因为您使用的是[self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView\u NibName]
创建节头并在数组中保留它们,我不认为UITableViewCell是为此创建的,但我不确定。您可能需要考虑前面的UITabeVIEW单元格视图,而不是使用其他的(可能是UIIVIEVIEW和UIABEL)。或者,您不能将剖面视图存储在数组中……按照您当前设置代码的方式,您不需要数组,创建新视图非常简单,您不需要担心。@AaronHayman的答案很有效(在我看来,接受和赏金应该归他所有,就目前的情况而言-这不适合评论!),但我想进一步说-你根本不应该使用单元格作为节头,也不应该使用出列机制来加载nib
节头视图不应该是单元格,使用它们代替常规视图可能会产生不可预见的效果,特别是当它们被取消使用时——当您这样做时,表格会保留这些可重用单元格的列表,当它们离开屏幕时会回收它们,但您的节头是不可重用的,每个节都有一个
在您的示例项目中,我将SectionHeaderView的超类更改为普通UIView,并将您的createSectionHeaderViews
方法更改为直接从NIB加载:
NSMutableArray *sectionHeaderViews = [[NSMutableArray alloc] init];
UINib *headerNib = [UINib nibWithNibName:SectionHeaderView_NibName bundle:nil];
for (int i = 0; i < 5; i++)
{
SectionHeaderView *sectionHeaderView = [[headerNib instantiateWithOwner:nil options:nil] objectAtIndex:0];
sectionHeaderView.textLabel.text = [NSString stringWithFormat:@"Section %d", i];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:sectionHeaderView action:@selector(handleTap:)];
[sectionHeaderView addGestureRecognizer:tapRecognizer];
sectionHeaderView.section = i;
sectionHeaderView.delegate = self;
[sectionHeaderViews addObject:sectionHeaderView];
}
self.sectionHeaderViews = sectionHeaderViews;
NSMutableArray*sectionHeaderViews=[[NSMutableArray alloc]init];
UINib*headerNib=[UINib-nibWithNibName:SectionHeaderView\u-NibName bundle:nil];
对于(int i=0;i<5;i++)
{
SectionHeaderView*SectionHeaderView=[[headerNib实例化所有者:nil选项:nil]对象索引:0];
sectionHeaderView.textLabel.text=[NSString stringWithFormat:@“Section%d”,i];
UITapGestureRecognizer*tapRecognizer=[[UITapGestureRecognizer alloc]initWithTarget:sectionHeaderView操作:@selector(handleTap:)];