虽然其他答案似乎有帮助并且部分完成了工作,但它并不能解决搜索栏无法接收用户触摸的问题,因为它会在您更改其框架时移动到其父视图的范围之外。
更糟糕的是,当您单击搜索栏使其成为第一响应者时,tableView 委托很可能会在搜索栏下方的单元格上调用tableView:didSelectRowAtIndexPath:。
为了解决上述问题,您需要将搜索栏包装在一个普通的 UIView 中,该视图能够处理发生在其边界之外的触摸。通过这种方式,您可以将这些触摸传递到搜索栏。
所以让我们先这样做:
class SearchBarView: UIView {
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
for subview in subviews {
if !subview.userInteractionEnabled { continue }
let newPoint = subview.convertPoint(point, fromView: self)
if CGRectContainsPoint(subview.bounds, newPoint) {
return subview.hitTest(newPoint, withEvent: event)
}
}
return super.hitTest(point, withEvent: event)
}
}
现在,我们有一个名为SearchBarView 的 UIView 子类,它能够接收发生在其边界之外的触摸。
其次,我们应该在视图控制器加载其视图时将搜索栏放入新视图中:
class TableViewController: UITableViewController {
private let searchBar = UISearchBar(frame: CGRectZero)
...
override func viewDidLoad() {
super.viewDidLoad()
...
searchBar.sizeToFit()
let searchBarView = SearchBarView(frame: searchBar.bounds)
searchBarView.addSubview(searchBar)
tableView.tableHeaderView = searchBarView
}
}
最后,我们应该在用户向下滚动表格视图时更新搜索栏的框架,使其保持固定在顶部:
override func scrollViewDidScroll(scrollView: UIScrollView) {
searchBar.frame.origin.y = max(0, scrollView.contentOffset.y)
}
结果如下:
--
重要提示:如果您的表格视图有部分,它们可能会遮住您的搜索栏,因此每次更新表格视图的bounds 时,您需要将搜索栏置于其顶部。
viewDidLayoutSubviews 是这样做的好地方:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
...
if let tableHeaderView = tableView.tableHeaderView {
tableView.bringSubviewToFront(tableHeaderView)
}
}
--
希望这会有所帮助。您可以从here下载示例项目。