Search code examples
iosswiftxcodenslayoutconstraint

Why is NSLayoutConstraint's identifier property not working in code?


I am trying to write some conditions where the same constraint is not added twice. For example if a view already has a bottom anchor constraint do not add it again. So I tried using the layout constraint identifier to uniquely identify a constraint so that if it is already exists dont add another constraint again. I do not have a storyboard, so I have written the below 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
        }
    }
}

But both times I am calling setPDFViewHeight method it says there is not identifier named "bottom" but it should the second time. I have also tried to get the constraints of the super view directly like below but the same issue there as well.

        for constraints in view.constraints {
            if constraints.identifier == "bottom" {
                isBottomAnchorSet = true
            }
        }

What am I doing wrong or does this identifier cannot be used this way?

Even an entirely different answer on how to avoid duplication of Layout constraints would also help. Thanks in advance.


Solution

  • I think in your situation it's better to keep the bottom constraint and just update the constant later on, when needed, like this:

    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
        }
    }
    

    Also the naming of the setPDFViewHeight may be misleading, because what it really does is that it set's the offset from the anchor, not the absolute height.