从 iOS 11 搜索控制器导航时不需要的 UITableView 重新加载动画
Unwanted UITableView reload animation when navigating from iOS 11 search controller
我有一个包含聊天列表的 table 视图的视图控制器,一个嵌入在导航项中的搜索控制器(iOS 11 功能)
let searchController = UISearchController(searchResultsController: nil)
searchController.dimsBackgroundDuringPresentation = false
navigationItem.searchController = searchController
definesPresentationContext = true
当用户点击 table 视图中的聊天时,应用程序会推送一个新的视图控制器和另一个包含该聊天消息的 table 视图。这就像它应该的那样工作:
问题是,当用户激活搜索控制器,找到一些聊天并点击它时,包含 table 视图和聊天消息的推送视图控制器会做一些非常奇怪的 动画table 不应发生的观点:
我在实际导航之前加载数据,并仅使用 table 视图上的 reload()
将其绑定到 viewDidLoad
中的 table 视图。有问题的 table 视图使用自动布局和自定义单元格。
该问题与 UITableView has unwanted animation when reloadData is called 非常相似,但对我而言,它仅在 iOS 11 搜索控制器处于活动状态时发生。
编辑:如果我删除 tableView.rowHeight = UITableViewAutomaticDimension
并使用固定高度 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
问题仍然存在
您可以尝试在出列并设置单元格内容后立即调用 cell.layoutIfNeeded()
iOS 11 完全改进了安全区域 API,包括滚动视图插入调整行为,忽略时可能会导致不需要的动画。因此,禁用带有不需要动画的滚动视图的自动内容插入调整:
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
} else {
// < iOS 11 logic
}
在 VC2 中重装前尝试延迟功能 table
DispatchQueue.main.asyncAfter(截止日期:.now() + 0.1) {
tableView.reloadData
}
否则
- 在
didSelect
中的 VC1 在推送到 VC2 之前退出搜索控制器的第一响应者
或
- In VC1 in
didSelect
resign first responder of search controller and set a delay before pushing to VC2.
就个人而言,我会在展示新的视图控制器之前简单地隐藏 searchView 控制器。
(例如,将 UIView.animates 与完成处理程序一起使用)
我不会尝试进一步调查,因为自 iOS11 以来,安全区域管理中存在一个深奥的问题。一个错误? :)
甚至启动屏幕布局也未正确处理。
如此多的专业徽标在发布时错过了中间部分!
不要在 viewDidLoad
或 viewWillAppear
中调用 reloadData()
方法。而不是在 viewDidLoad
中使用空数据重新加载您的 tableView,这样您的 tableView
将不显示任何内容,然后在您的 viewDidAppear
中调用 reloadData()
方法来加载您的所有聊天记录。这将限制您的 tableView 加载不需要的动画。
var shouldShowEmpty = true
func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
}
func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
shouldShowEmpty = false
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if shouldShowEmpty {
return 0
}
return yourArray.count
}
如果您只是在推送新的 viewController 之前隐藏搜索栏,那么它可能会解决您的问题。
您需要为 searchBarCancelButton 创建一个全局变量,并在搜索内容时从其子视图中找到取消按钮
let buttons = searchController.searchBar.subviews.first?.subviews.filter { (view) -> Bool in
return NSStringFromClass(view.classForCoder) == "UINavigationButton"
} as? [UIButton]
searchBarCancelButton = buttons?.first
那你就可以手动取消了。
self.searchBarCancelButton?.sendActions(for: .touchUpInside)
根据附件,看起来由于自动布局,单元格的元素高度为零(UILabel or UIImageView
)然后突然当 table 视图重新加载时它获取单元格内的数据,这增加了它导致此动画的高度(自动尺寸或其他)。
尝试在没有动画的情况下推送它或尝试设置修复单元格元素的高度和宽度并检查它是否仍在显示此动画。
您是否在不调用 UISearchBar 的情况下进行了检查,如果您 select 在任何单元格上都发生了相同的动画??还是您尝试删除单元格上的 UISearchbar 和 select 并检查动画部分?
请分享您的代码,以便我们看得更清楚。
我遇到过类似的问题,我相信解决方案是一样的。键盘导致了问题,更正确的是,keyboardWillHideNotification 触发器。您在底部有文本字段,它可能会监听键盘 show/hide 的通知,如果您为底部约束设置动画,则触发 layoutIfNeeded() 以便您的键盘不会与文本字段重叠。因此,当您在搜索文本字段中完成搜索时,会在不需要的时间触发 keyboardWillHideNotification。我通过调用解决了我的问题:
resignFirstResponder()
对于导致此事件的文本字段。在我的例子中,那是在按下按钮之后,在你的例子中,我相信它在搜索 table 视图中的 didSelect tableView 单元格中。
如果您在这个问题上仍然很活跃,请告诉我您是否设法解决了它。为了解决这个问题,我绞尽了脑汁,这显然是那么简单明了。
我有一个包含聊天列表的 table 视图的视图控制器,一个嵌入在导航项中的搜索控制器(iOS 11 功能)
let searchController = UISearchController(searchResultsController: nil)
searchController.dimsBackgroundDuringPresentation = false
navigationItem.searchController = searchController
definesPresentationContext = true
当用户点击 table 视图中的聊天时,应用程序会推送一个新的视图控制器和另一个包含该聊天消息的 table 视图。这就像它应该的那样工作:
问题是,当用户激活搜索控制器,找到一些聊天并点击它时,包含 table 视图和聊天消息的推送视图控制器会做一些非常奇怪的 动画table 不应发生的观点:
我在实际导航之前加载数据,并仅使用 table 视图上的 reload()
将其绑定到 viewDidLoad
中的 table 视图。有问题的 table 视图使用自动布局和自定义单元格。
该问题与 UITableView has unwanted animation when reloadData is called 非常相似,但对我而言,它仅在 iOS 11 搜索控制器处于活动状态时发生。
编辑:如果我删除 tableView.rowHeight = UITableViewAutomaticDimension
并使用固定高度 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
问题仍然存在
您可以尝试在出列并设置单元格内容后立即调用 cell.layoutIfNeeded()
iOS 11 完全改进了安全区域 API,包括滚动视图插入调整行为,忽略时可能会导致不需要的动画。因此,禁用带有不需要动画的滚动视图的自动内容插入调整:
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
} else {
// < iOS 11 logic
}
在 VC2 中重装前尝试延迟功能 table
DispatchQueue.main.asyncAfter(截止日期:.now() + 0.1) { tableView.reloadData }
否则
- 在
didSelect
中的 VC1 在推送到 VC2 之前退出搜索控制器的第一响应者
或
- In VC1 in
didSelect
resign first responder of search controller and set a delay before pushing to VC2.
就个人而言,我会在展示新的视图控制器之前简单地隐藏 searchView 控制器。 (例如,将 UIView.animates 与完成处理程序一起使用)
我不会尝试进一步调查,因为自 iOS11 以来,安全区域管理中存在一个深奥的问题。一个错误? :)
甚至启动屏幕布局也未正确处理。 如此多的专业徽标在发布时错过了中间部分!
不要在 viewDidLoad
或 viewWillAppear
中调用 reloadData()
方法。而不是在 viewDidLoad
中使用空数据重新加载您的 tableView,这样您的 tableView
将不显示任何内容,然后在您的 viewDidAppear
中调用 reloadData()
方法来加载您的所有聊天记录。这将限制您的 tableView 加载不需要的动画。
var shouldShowEmpty = true
func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
}
func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
shouldShowEmpty = false
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if shouldShowEmpty {
return 0
}
return yourArray.count
}
如果您只是在推送新的 viewController 之前隐藏搜索栏,那么它可能会解决您的问题。
您需要为 searchBarCancelButton 创建一个全局变量,并在搜索内容时从其子视图中找到取消按钮
let buttons = searchController.searchBar.subviews.first?.subviews.filter { (view) -> Bool in
return NSStringFromClass(view.classForCoder) == "UINavigationButton"
} as? [UIButton]
searchBarCancelButton = buttons?.first
那你就可以手动取消了。
self.searchBarCancelButton?.sendActions(for: .touchUpInside)
根据附件,看起来由于自动布局,单元格的元素高度为零(UILabel or UIImageView
)然后突然当 table 视图重新加载时它获取单元格内的数据,这增加了它导致此动画的高度(自动尺寸或其他)。
尝试在没有动画的情况下推送它或尝试设置修复单元格元素的高度和宽度并检查它是否仍在显示此动画。
您是否在不调用 UISearchBar 的情况下进行了检查,如果您 select 在任何单元格上都发生了相同的动画??还是您尝试删除单元格上的 UISearchbar 和 select 并检查动画部分?
请分享您的代码,以便我们看得更清楚。
我遇到过类似的问题,我相信解决方案是一样的。键盘导致了问题,更正确的是,keyboardWillHideNotification 触发器。您在底部有文本字段,它可能会监听键盘 show/hide 的通知,如果您为底部约束设置动画,则触发 layoutIfNeeded() 以便您的键盘不会与文本字段重叠。因此,当您在搜索文本字段中完成搜索时,会在不需要的时间触发 keyboardWillHideNotification。我通过调用解决了我的问题:
resignFirstResponder()
对于导致此事件的文本字段。在我的例子中,那是在按下按钮之后,在你的例子中,我相信它在搜索 table 视图中的 didSelect tableView 单元格中。
如果您在这个问题上仍然很活跃,请告诉我您是否设法解决了它。为了解决这个问题,我绞尽了脑汁,这显然是那么简单明了。