添加 UISearchController 并以编程方式使用约束对其进行定位

Posted

技术标签:

【中文标题】添加 UISearchController 并以编程方式使用约束对其进行定位【英文标题】:Adding a UISearchController and position it with constraints programmatically 【发布时间】:2015-08-11 18:09:28 【问题描述】:

我想以编程方式向 UISearchController 添加前导、尾随、底部和宽度约束。这是我的代码:

@IBOutlet weak var navigationBar: UIView!

// create search bar
searchBar = UISearchController(searchResultsController: nil)
navigationBar.addSubview(searchBar.searchBar)
searchBar.searchBar.translatesAutoresizingMaskIntoConstraints = false

let leftConstraint = NSLayoutConstraint(item: searchBar.searchBar, attribute: .Leading, relatedBy: .Equal, toItem: navigationBar, attribute: .Leading, multiplier: 1, constant: 0)

let rightConstraint = NSLayoutConstraint(item: searchBar.searchBar, attribute: .Trailing, relatedBy: .Equal, toItem: navigationBar, attribute: .Trailing, multiplier: 1, constant: 0)

let bottomConstraint = NSLayoutConstraint(item: searchBar.searchBar, attribute: .Bottom, relatedBy: .Equal, toItem: navigationBar, attribute: .Bottom, multiplier: 1, constant: 0)

let heightConstraint = NSLayoutConstraint(item: searchBar.searchBar, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 44)

navigationBar.addConstraints([leftConstraint, rightConstraint, bottomConstraint, widthConstraint])

运行应用程序时,搜索栏正确显示,但是当我按下搜索栏时,它会缩小,如果我再次按下,应用程序就会崩溃。这是输出:

2015-08-12 20:20:37.696 Contacts++[96997:8547485] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb22580c7a0 UIView:0x7fb225817b20.leading == UIView:0x7fb223449860.leading>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
2015-08-12 20:20:37.697 Contacts++[96997:8547485] *** Assertion failure in -[UIView _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3491.2.5/NSLayoutConstraint_UIKitAdditions.m:590

【问题讨论】:

叫你 searchController 'searchBar' 有点奇怪。 您真的想要将导航栏的宽度设置为44磅吗? 我已经用现在到底发生了什么来编辑问题。 如果您正在部署到 ios8 或更高版本,请尝试将 navigationBar.addConstraints( 替换为 NSLayoutConstraint.activateConstraints( 发生同样的问题 【参考方案1】:

为什么需要创建 'UISearchController' 的实例并获取它的 searchBar?

为什么不直接从 UISearchBar 制作 searchBar?

// create a searchBar from UISearchBar
let searchBar = UISearchBar(frame: CGRectZero)

// add searchBar to navigationBar
navigationController?.navigationBar.addSubview(searchBar)

// call sizeToFit.. this will set the frame of the searchBar to exactly the same as the size of the allowable frame of the navigationBar
searchBar.sizeToFit()

// now reframe the searchBar to add some margins
var frame = searchBar.frame
frame.origin.x = 20
frame.size.width -= 40
searchBar.frame = frame // set new frame with margins

注意:你不需要任何这些约束来实现这一点。

但如果你真的更喜欢约束,这里是没有崩溃的约束代码。

let searchBar = UISearchBar(frame: CGRectZero)
navigationController?.navigationBar.addSubview(searchBar)
searchBar.setTranslatesAutoresizingMaskIntoConstraints(false)

let leftConstraint = NSLayoutConstraint(item: searchBar, attribute: .Leading, relatedBy: .Equal, toItem: navigationController?.navigationBar, attribute: .Leading, multiplier: 1, constant: 20) // add margin

let bottomConstraint = NSLayoutConstraint(item: searchBar, attribute: .Bottom, relatedBy: .Equal, toItem: navigationController?.navigationBar, attribute: .Bottom, multiplier: 1, constant: 1)

let topConstraint = NSLayoutConstraint(item: searchBar, attribute: .Top, relatedBy: .Equal, toItem: navigationController?.navigationBar, attribute: .Top, multiplier: 1, constant: 1)

let widthConstraint = NSLayoutConstraint(item: searchBar, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: self.view.frame.size.width - 40) // - margins from both sides

navigationController?.navigationBar.addConstraints([leftConstraint, bottomConstraint, topConstraint, widthConstraint])

【讨论】:

嗨,它工作得很好,但是当我触摸它时我的搜索栏消失了。有什么想法吗? @greenpoisononeTV 这可能与完全改变导航栏行为的 iOS11 更新有关。【参考方案2】:

您真的想要将 navigatinBar 的 宽度 设置为 44 磅吗?宽度是水平的。通过添加尾随和前导约束,您已经有了宽度约束。

【讨论】:

我好惭愧,对,应该是身高。但是我仍然得到相同的效果,按内部搜索时搜索会缩小,然后如果我再次单击,它就会崩溃。这是 translatesAutoresizingMaskIntoConstraints = false 的情况。如果我将其设置为 true,它将正常工作,但未正确对齐。我在底部和搜索栏之间有差距。 知道如何解决这个问题吗?

以上是关于添加 UISearchController 并以编程方式使用约束对其进行定位的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tvOS 的同一视图中显示 UISearchController?

添加 UISearchController 时导航栏变为白色

添加 UISearchController 后 UITableView 可以滚动到顶部太远

UISearchController 在编辑时添加偏移量

在 UISearchController 下添加水平滚动过滤器选项

如何在嵌入 UINavigationController 的 UISearchController 中添加范围按钮