为什么NSLayoutConstraint的identifier属性在代码中不起作用?

问题描述

我正在尝试写一些条件,其中相同约束没有两次添加。例如,如果视图已经具有底部锚点约束,则不要再次添加它。因此,我尝试使用布局约束标识符来唯一标识约束,以便如果该约束已经存在,就不要再添加另一个约束。我没有情节提要,所以我写了下面的代码:

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: bottom <NSLayoutConstraint:0x60000208bc00 'bottom' UIView:0x7fbfa5407fa0.bottom == UIView:0x7fbfa54084d0.bottom   (active)>
Bottom Anchor already set

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...