【问题标题】:UISearchBar disappears from tableHeaderView when using beginUpdates/endUpdates使用 beginUpdates/endUpdates 时 UISearchBar 从 tableHeaderView 中消失
【发布时间】:2016-12-01 08:55:02
【问题描述】:

我有一个带有UISearchController 的表视图控制器,它将UISearchBar 设置为tableView.tableHeaderView。更新搜索结果时,我使用beginUpdatesendUpdates等相关方法更新table view的数据。

这会使搜索栏消失; tableHeaderView 设置为与搜索栏大小相同的空的通用UIView。如果我只是使用reloadData 而不是整个beginUpdates/endUpdates 过程,一切都很好。

表格视图控制器嵌入在常规视图控制器中;没有涉及导航控制器。这是重现问题所需的表视图控制器的完整实现:​​

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
    self.searchController.searchResultsUpdater = self;
    self.searchController.dimsBackgroundDuringPresentation = NO;

    self.tableView.tableHeaderView = self.searchController.searchBar;
}

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

为什么会导致搜索栏被替换为空白视图,如何避免?

【问题讨论】:

  • 您是否尝试过更改 viewController/Navigation 控制器上的“半透明”属性?我记得我曾经遇到过这个问题,如果我没记错的话“半透明”它与它有关..

标签: ios uitableview cocoa-touch uisearchbar uisearchcontroller


【解决方案1】:

当你第一次点击UISearchController'ssearchBar时,searchBar动画大约需要0.5s。但是self.tableView.endUpdates()被委托方法立即调用,动画被中断了。
searchBar 卡在动画中间,看不到它的 UI:

一种解决方法是检查 searchBar 是否处于动画状态,并在它处于动画状态时延迟 self.tableView.endUpdates()

func updateSearchResultsForSearchController(searchController: UISearchController){
    self.tableView.beginUpdates()
    //Do some updates

    if !searchController.searchBar.showsCancelButton{
        self.tableView.performSelector(#selector(UITableView.endUpdates), withObject: nil, afterDelay: 1)

    }else{
        self.tableView.endUpdates()
    }
}

【讨论】:

  • 感谢您的回答。我认为您对动画有所了解。我尝试过[CATransaction setCompletionBlock:] 之类的技巧,但无济于事。您的解决方法似乎特别hacky,而且不适用于原始问题。可能是因为它不像我提供的可重现示例那样做作,并且在beginUpdatesendUpdates 之间做了更多的工作。
  • 在这种情况下,您应该尝试使用另一个 tableViewController 初始化您的“UISearchController”,并使用第二个 tableViewController 进行所有更新。
  • [[UISearchController alloc] initWithSearchResultsController:...]?我想这是一个解决方案,但我想保留与原始表格视图相关的所有功能,例如手势等。不过,如果没有其他办法,没有什么是一点点重构解决不了的。
  • 然后尝试使用 UISearchBarDelegate searchBarTextDidBeginEditing:,并把你的第一个 endUpdates 放在那里。
  • 不幸的是,在searchBarTextDidBeginEditing: 工作似乎没有任何改变。
【解决方案2】:

关于beginUpdates, endUpdates and reloadData的小修改

beginUpdates : :开始一系列插入、删除或选择表视图的行和部分的方法调用。 如果您希望后续的插入、删除和选择操作(例如,cellForRowAtIndexPath: 和 indexPathsForVisibleRows)同时进行动画处理,请调用此方法。您还可以使用此方法后跟 endUpdates 方法来动画行高的变化,而无需重新加载单元格。这组方法必须以调用 endUpdates 结束。这些方法对可以嵌套。如果您不在此块内进行插入、删除和选择调用,则行数等表属性可能会变得无效。你不应该在组内调用 reloadData;如果您在组内调用此方法,则必须自己执行任何动画。

endUpdates : 结束一系列插入、删除、选择或重新加载表视图的行和部分的方法调用。 您调用此方法来括起一系列以 beginUpdates 开头的方法调用,这些方法调用包括插入、删除、选择和重新加载表视图的行和部分的操作。当您调用 endUpdates 时,UITableView 会同时为操作设置动画。 beginUpdates 和 endUpdates 的调用可以嵌套。如果您不在此块内进行插入、删除和选择调用,则行数等表属性可能会变得无效。

reloadData : 重新加载表格视图的行和部分。 调用此方法可重新加载用于构建表格的所有数据,包括单元格、节页眉和页脚、索引数组等。为了提高效率,表格视图只重新显示那些可见的行。如果表因重新加载而缩小,它会调整偏移量。表视图的委托或数据源在它希望表视图完全重新加载其数据时调用此方法。不应在插入或删除行的方法中调用它,尤其是在通过调用 beginUpdates 和 endUpdates 实现的动画块中。

现在在搜索的情况下,我们不知道每次搜索结果数据不同时也会影响哪些行,我认为不应该使用

[self.tableView beginUpdates];
[self.tableView endUpdates];

当您在 tableview 上执行 insert, update or delete 操作时使用它并且您知道它的 indexPath

最好使用[self.tableView reloadData];,因为它只会更新表格视图中的可见行或部分。另请参阅 Apple 的 Table Search with UISearchController 示例代码,也推荐使用 reloadData

进行相应的更改,一切顺利。

编码愉快:)

【讨论】:

  • 我知道使用reloadData 可以解决问题,尽管这并不能解释为什么不能使用beginUpdatesendUpdates
  • @Håvard 这就是我所解释的,何时使用beginUpdates and endUpdatesreloadData
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 2016-03-19
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多