为什么 NSLayoutConstraints 标识符 属性 在代码中不起作用?
Why is NSLayoutConstraint's identifier property not working in code?
我正在尝试编写一些不添加两次相同约束的条件。例如,如果视图已经具有底部锚点约束,则不要再次添加它。所以我尝试使用布局约束标识符来唯一标识一个约束,这样如果它已经存在就不要再添加另一个约束。我没有故事板,所以我写了下面的代码:
class PDFViewer: UIViewController {
var quickLookController = QLPreviewController()
override func viewDidLoad()
if let quickView = quickLookController.view {
self.view.addSubview(quickView)
}
{
quickLookController.view.translatesAutoresizingMaskIntoConstraints = false
quickLookController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
quickLookController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
quickLookController.view.topAnchor.constraint(equalTo: navView.bottomAnchor).isActive = true
setPDFViewHeight(height: 100)
setPDFViewHeight(height: 100)
}
open func setPDFViewHeight(height: CGFloat) {
var isBottomAnchorSet = false
if let superView = quickLookController.view.superview {
for constraints in superView.constraints {
if constraints.identifier == "bottom" {
isBottomAnchorSet = true
}
else {
print(false)
}
}
}
if !isBottomAnchorSet {
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).identifier = "bottom"
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
}
但是我两次调用 setPDFViewHeight
方法时它都说没有名为 "bottom"
的标识符,但第二次应该是。我也试过像下面这样直接获取超级视图的约束,但那里也有同样的问题。
for constraints in view.constraints {
if constraints.identifier == "bottom" {
isBottomAnchorSet = true
}
}
我做错了什么或者这个标识符不能这样使用?
即使是关于如何避免布局约束重复的完全不同的答案也会有所帮助。提前致谢。
我认为在您的情况下,最好保留底部约束并稍后在需要时更新常量,如下所示:
class PDFViewer: UIViewController {
var quickLookController = QLPreviewController()
var bottomConstraint: NSLayoutConstraint?
override func viewDidLoad()
if let quickView = quickLookController.view {
self.view.addSubview(quickView)
}
quickLookController.view.translatesAutoresizingMaskIntoConstraints = false
bottomConstraint = quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
NSLayoutConstraint.activate([
quickLookController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
quickLookController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
quickLookController.view.topAnchor.constraint(equalTo: navView.bottomAnchor),
bottomConstraint
])
setPDFViewHeight(height: 100)
setPDFViewHeight(height: 100)
open func setPDFViewHeight(height: CGFloat) {
bottomConstraint.constant = height
}
}
此外 setPDFViewHeight
的命名可能会产生误导,因为它真正做的是设置距锚点的偏移量,而不是绝对高度。
问题是您正在创建两个底部约束:
// this creates a constraint
// with an identifier
// but does not activate it
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).identifier = "bottom"
// this creates a constraint
// WITHOUT an identifier
// and activates it
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
试一试:
open func setPDFViewHeight(height: CGFloat) {
var isBottomAnchorSet = false
if let superView = quickLookController.view.superview {
for constraint in superView.constraints {
print("constraint identifier:", constraint.identifier ?? "no id", constraint)
if constraint.identifier == "bottom" {
isBottomAnchorSet = true
print("Bottom Anchor already set")
}
}
if !isBottomAnchorSet {
print("Creating Bottom Anchor")
let c = quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
c.identifier = "bottom"
c.isActive = true
}
}
}
要对其进行测试,请将您的双重调用替换为:
print("First call")
print()
setPDFViewHeight(height: 100)
print()
print("Second call")
print()
setPDFViewHeight(height: 100)
这是我得到的输出:
First call
constraint identifier: no id <NSLayoutConstraint:0x600002086030 H:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
constraint identifier: no id <NSLayoutConstraint:0x600002085fe0 UIView:0x7fbfa5407fa0.trailing == UIView:0x7fbfa54084d0.trailing (active)>
constraint identifier: no id <NSLayoutConstraint:0x600002085f40 V:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
Creating Bottom Anchor
Second call
constraint identifier: no id <NSLayoutConstraint:0x600002086030 H:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
constraint identifier: no id <NSLayoutConstraint:0x600002085fe0 UIView:0x7fbfa5407fa0.trailing == UIView:0x7fbfa54084d0.trailing (active)>
constraint identifier: no id <NSLayoutConstraint:0x600002085f40 V:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
constraint identifier: bottom <NSLayoutConstraint:0x60000208bc00 'bottom' UIView:0x7fbfa5407fa0.bottom == UIView:0x7fbfa54084d0.bottom (active)>
Bottom Anchor already set
我正在尝试编写一些不添加两次相同约束的条件。例如,如果视图已经具有底部锚点约束,则不要再次添加它。所以我尝试使用布局约束标识符来唯一标识一个约束,这样如果它已经存在就不要再添加另一个约束。我没有故事板,所以我写了下面的代码:
class PDFViewer: UIViewController {
var quickLookController = QLPreviewController()
override func viewDidLoad()
if let quickView = quickLookController.view {
self.view.addSubview(quickView)
}
{
quickLookController.view.translatesAutoresizingMaskIntoConstraints = false
quickLookController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
quickLookController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
quickLookController.view.topAnchor.constraint(equalTo: navView.bottomAnchor).isActive = true
setPDFViewHeight(height: 100)
setPDFViewHeight(height: 100)
}
open func setPDFViewHeight(height: CGFloat) {
var isBottomAnchorSet = false
if let superView = quickLookController.view.superview {
for constraints in superView.constraints {
if constraints.identifier == "bottom" {
isBottomAnchorSet = true
}
else {
print(false)
}
}
}
if !isBottomAnchorSet {
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).identifier = "bottom"
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
}
但是我两次调用 setPDFViewHeight
方法时它都说没有名为 "bottom"
的标识符,但第二次应该是。我也试过像下面这样直接获取超级视图的约束,但那里也有同样的问题。
for constraints in view.constraints {
if constraints.identifier == "bottom" {
isBottomAnchorSet = true
}
}
我做错了什么或者这个标识符不能这样使用?
即使是关于如何避免布局约束重复的完全不同的答案也会有所帮助。提前致谢。
我认为在您的情况下,最好保留底部约束并稍后在需要时更新常量,如下所示:
class PDFViewer: UIViewController {
var quickLookController = QLPreviewController()
var bottomConstraint: NSLayoutConstraint?
override func viewDidLoad()
if let quickView = quickLookController.view {
self.view.addSubview(quickView)
}
quickLookController.view.translatesAutoresizingMaskIntoConstraints = false
bottomConstraint = quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
NSLayoutConstraint.activate([
quickLookController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
quickLookController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
quickLookController.view.topAnchor.constraint(equalTo: navView.bottomAnchor),
bottomConstraint
])
setPDFViewHeight(height: 100)
setPDFViewHeight(height: 100)
open func setPDFViewHeight(height: CGFloat) {
bottomConstraint.constant = height
}
}
此外 setPDFViewHeight
的命名可能会产生误导,因为它真正做的是设置距锚点的偏移量,而不是绝对高度。
问题是您正在创建两个底部约束:
// this creates a constraint
// with an identifier
// but does not activate it
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).identifier = "bottom"
// this creates a constraint
// WITHOUT an identifier
// and activates it
quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
试一试:
open func setPDFViewHeight(height: CGFloat) {
var isBottomAnchorSet = false
if let superView = quickLookController.view.superview {
for constraint in superView.constraints {
print("constraint identifier:", constraint.identifier ?? "no id", constraint)
if constraint.identifier == "bottom" {
isBottomAnchorSet = true
print("Bottom Anchor already set")
}
}
if !isBottomAnchorSet {
print("Creating Bottom Anchor")
let c = quickLookController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
c.identifier = "bottom"
c.isActive = true
}
}
}
要对其进行测试,请将您的双重调用替换为:
print("First call")
print()
setPDFViewHeight(height: 100)
print()
print("Second call")
print()
setPDFViewHeight(height: 100)
这是我得到的输出:
First call
constraint identifier: no id <NSLayoutConstraint:0x600002086030 H:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
constraint identifier: no id <NSLayoutConstraint:0x600002085fe0 UIView:0x7fbfa5407fa0.trailing == UIView:0x7fbfa54084d0.trailing (active)>
constraint identifier: no id <NSLayoutConstraint:0x600002085f40 V:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
Creating Bottom Anchor
Second call
constraint identifier: no id <NSLayoutConstraint:0x600002086030 H:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
constraint identifier: no id <NSLayoutConstraint:0x600002085fe0 UIView:0x7fbfa5407fa0.trailing == UIView:0x7fbfa54084d0.trailing (active)>
constraint identifier: no id <NSLayoutConstraint:0x600002085f40 V:|-(0)-[UIView:0x7fbfa5407fa0] (active, names: '|':UIView:0x7fbfa54084d0 )>
constraint identifier: bottom <NSLayoutConstraint:0x60000208bc00 'bottom' UIView:0x7fbfa5407fa0.bottom == UIView:0x7fbfa54084d0.bottom (active)>
Bottom Anchor already set