Search code examples
iosswiftuiimageviewnslayoutconstraint

I can't see the mistake at this NSLayoutConstraints


i would like to place three View in following layout:

ImageView: II Textlabel: TT TitleLabel: TL Space: S

SSSSSS-TL-SSSSS
IISSSSTT--------------
SSSSSSSSSSSSSS

My current Code for this is as follows:

let views = ["imageView": imageView, "titleLabel": titleLabel, "messageLabel": messageLabel] as [String : Any]
        var constraints = [NSLayoutConstraint]()

        constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[imageView]-[titleLabel]|", options: [], metrics: nil, views: views)
        constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-(==20@900)-[titleLabel]-(==20@900)-|", options: [], metrics: nil, views: views)
        constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[imageView]-[messageLabel]-(==20@900)-|", options: [], metrics: nil, views: views)
        constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[imageView]-(==30@200)-[titleLabel]-(==8@200)-[messageLabel]-(==30@200)-|", options: [], metrics: nil, views: views)
        imageHeightConstraint = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: imageView, attribute: .height, multiplier: 0, constant: 0)
        constraints.append(imageHeightConstraint!)

It works... almost fine. I'm not receiving the layout i want, but i receive an acceptable layout with a few bugs.

But the console also is reporting a few things which makes me worrying:

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "", "", "", "" )

Could someone please help me? I'm not having really much experience with NSLayoutConstraints in General, specially not in Swift.

It would be great if you could help me getting the wished layout or fix the things the console want be fixed.

Thanks a lot!


Solution

  • Let's debug this. If you are using visual format constraints, the idea would be to have one Horizontal and Vertical constraints for each view. But I see you have multiple constraints for a view.

    Also, remember to set translateAutoresizingMask for each view to false.

    Let's track the constraints.

      constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[imageView]-[titleLabel]|", options: [], metrics: nil, views: views)
    

    Here ImageView and titleLabel have 1 horizonatal contsraints. Moving ahead, I have put the total counting below.

      constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-(==20@900)-[titleLabel]-(==20@900)-|", options: [], metrics: nil, views: views)
      constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[imageView]-[messageLabel]-(==20@900)-|", options: [], metrics: nil, views: views)
    
      constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[imageView]-(==30@200)-[titleLabel]-(==8@200)-[messageLabel]-(==30@200)-|", options: [], metrics: nil, views: views)
    

    The above constraint is conflicting. Why? because you have already declared a Vertical constraints [ImageView - messageLabel] and Now you are making [imageView - titleLabel - messageLabel].

      imageHeightConstraint = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: imageView, attribute: .height, multiplier: 0, constant: 0)
    

    The above constraint is also of no use because you are setting the height constraints of imageView to itself, it should be with its superview or a constant.

    Counting above, you have extra constraints lying.

      ImageView: H: 1  and V: 2  // You have extra height contraitns.
      titleLabel: H: 1 and V: 2
      messageLabel: H: 0 and V: 1
    

    The answer is simple, you just need one-one constraint for each. For e.g.

      // ImageView contrainst
      constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[imageView]-[titleLabel]|", options: [], metrics: nil, views: views)
      constraints(withVisualFormat: "V:|[imageView]-(==30@200)-[titleLabel]-(==8@200)-[messageLabel]-(==30@200)-|", options: [], metrics: nil, views: views)