Search code examples
iosswiftnslayoutconstraint

Adding Constraint Programmatically Does Not Work


I'm setting constraints to image view programmatically like so:

        imgScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        imgScrollView.showsHorizontalScrollIndicator = false
        imgScrollView.showsVerticalScrollIndicator = false
        imgScrollView.bouncesZoom = false
        imgScrollView.bounces = false

        view.addSubview(imgScrollView)

        imgScrollView.translatesAutoresizingMaskIntoConstraints = false
        imgScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        imgScrollView.bottomAnchor.constraint(equalTo: toolBar.topAnchor, constant: -100).isActive = true
        imgScrollView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 0).isActive = true
        imgScrollView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: 0).isActive = true



        // add image view to scrollview
        imgView = UIImageView(frame: CGRect(x: 0, y: 0,width: 100, height: 100))

        imgScrollView.addSubview(imgView)
        imgView.translatesAutoresizingMaskIntoConstraints = false

        imgView.topAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.topAnchor, constant: 0).isActive = true
        imgView.bottomAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.bottomAnchor, constant: 0).isActive = true
        imgView.leftAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.leftAnchor, constant: 0).isActive = true
        imgView.rightAnchor.constraint(equalTo: imgScrollView.contentLayoutGuide.rightAnchor, constant: 0).isActive = true


        imgView.widthAnchor.constraint(equalTo: imgScrollView.widthAnchor, multiplier: 1).isActive = true

Now later on with button tap I'm adding additional constraint

imgView.heightAnchor.constraint(equalTo: imgScrollView.heightAnchor, multiplier: 1).isActive = true

However the constraint is not being added. Why is it happening?


Solution

  • Your implementation logic working for me.

    • Left image show implementation without height constraint.
    • Right image show button pressed with height constraint.

    In function viewDidLoad

    override func viewDidLoad() {
      super.viewDidLoad()
      view.backgroundColor = .white
      scrollView.isScrollEnabled = true
      scrollView.bounces = false
      scrollView.alwaysBounceVertical = true
      imageView.image = UIImage(color: .lightGray)
    
      navigationItem.rightBarButtonItem = barButtonItem
      view.addSubview(scrollView)
      scrollView.addSubview(imageView)
    
      scrollView.translatesAutoresizingMaskIntoConstraints = false
      imageView.translatesAutoresizingMaskIntoConstraints = false
      NSLayoutConstraint.activate([
        scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
        scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor)
      ])
      NSLayoutConstraint.activate([
        imageView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
        imageView.leftAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leftAnchor),
        imageView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
        imageView.rightAnchor.constraint(equalTo: scrollView.contentLayoutGuide.rightAnchor),
        imageView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
      ])
    }
    

    In function buttonPressed

    @objc func buttonPressed() {
      navigationItem.rightBarButtonItem = nil
      UIView.animate(withDuration: 1) {
        NSLayoutConstraint.activate([
          self.imageView.heightAnchor.constraint(equalTo: self.scrollView.heightAnchor)
        ])
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()
      }
    }
    

    UIImage util Create UIImage with solid color in Swift

    fileprivate extension UIImage {
      convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
        let rect = CGRect(origin: .zero, size: size)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        color.setFill()
        UIRectFill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        guard let cgImage = image?.cgImage else { return nil }
        self.init(cgImage: cgImage)
      }
    }