我的问题是删除UITableView中的“不可见”行。当我说隐形时,我指的是屏幕上没有显示的行。例如,通过调用UITableView方法- (NSArray *)visibleCells
未返回的所有行。
我问这个是因为我正在开发一个“可扩展的”UITableView。有点像树。你可以有一个这样的表:
当您点击"Menu 1"
时,单元格"Menu 1.1"
和"Menu 1.2"
将会显示或消失。我这样做只需插入或删除带动画的单元格。
问题是,如果我有长菜单并且用户滚动,例如,如果“菜单1”的一半行被隐藏(不可见,不显示在屏幕上,只有向下滚动时才可见)和用户想要减少“菜单1”这将导致我的应用程序崩溃,因为我正在尝试删除不可见的行。
实际的错误消息是:
* 由于未捕获的异常'NSInternalInconsistencyException'而终止应用,原因:'无效更新:无效 第0节中的行数。包含在中的行数 更新后的现有部分(11)必须等于数量 更新前的该部分中包含的行(15),加号或减号 从该部分插入或删除的行数(插入0, 删除0)加上或减去移入或移出的行数 该部分(0移入,0移出)。'
如果我对可见的所有行进行完全相同的操作,那么应用程序和菜单的问题就没有问题。
答案 0 :(得分:1)
在tableview更新调用中,您需要更新tableview数据源以及tableview。您可以使用UITableView的indexPathsForVisibleRows方法来查找从源中删除对象的位置,并更新您的表。
答案 1 :(得分:0)
感谢各位的回答。我所做的是使用" indexPathsForVisibleRows" 来获取屏幕上显示的行而不是的indexPaths,我只是更新了我的模型并调用了" reloadData" 更新我的表格。这不是我期望的理想解决方案,但它有效。
我仍然不明白为什么" -deleteRowsAtIndexPaths" 不适用于不在屏幕上但实际存在于表格中的行。
答案 2 :(得分:0)
我有类似的问题,这是我的解决方案。基本上,解决方案涉及更改单元格高度以“隐藏”它们。
我已将节标题更改为自定义UIControl,看起来像任何其他单元格,并实现了follow方法来“隐藏”所选节之外的行:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == _selectedSection) {
// If it is the selected section then the cells are "open"
return 60.0;
} else {
// If is not the selected section then "close" the cells
return 0.0;
}
}
对于自定义标题,我使用了以下代码:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
CGFloat height = [self tableView:tableView heightForHeaderInSection:section];
// Here you can use whatever you want
CGFloat width = 640.0;
UIControl *view = [[UIControl alloc] initWithFrame:CGRectMake(0.0, 0.0, width, height)];
view.tag = section;
// This code is used by my custom UIControl
//
// to change the style for each state
// view.sectionSelected = (section == _selectedSection);
//
// and to change the title
// view.title = [self tableView:tableView titleForHeaderInSection:section];
// This event is used to "close" or "open" the sections
[view addTarget:self action:@selector(didSelectSectionHeader:) forControlEvents:UIControlEventTouchUpInside];
return view;
}
为了更具吸引力,我已经为以下方法添加了动画:
- (void)didSelectSectionHeader:(id)sender
{
if ([sender isKindOfClass:[UIControl class]]) {
// Save the old section index
int oldSelection = _selectedSection;
// Get the new section index
int tag = ((UIControl *)sender).tag;
// Get sections quantity
int numSections = [self numberOfSectionsInTableView:_tableView];
// Check if the user is closing the selected section
if (tag == _selectedSection) {
_selectedSection = -1;
} else {
_selectedSection = tag;
}
// Begin animations
[_tableView beginUpdates];
// Open the new selected section
if (_selectedSection >= 0 && _selectedSection < numSections) {
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:_selectedSection] withRowAnimation:UITableViewRowAnimationAutomatic];
}
// Close the old selected section
if (oldSelection >= 0 && oldSelection < numSections) {
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:oldSelection] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[_tableView endUpdates];
}
}