Warm tip: This article is reproduced from stackoverflow.com, please click
autolayout nslayoutconstraint swift

A layout issue (NSLayoutConstraint) in an iOS app

发布于 2020-03-27 10:18:52

In an iOS app I have an autolayout issue.

The 2 following screenshots show the problem.

enter image description here

enter image description here

The switch (UISwitch object) on the right is displaced horizontally, when it should be fixed. Can anyone see what is happening?

It is true that the string on the left is changing length, but I think (according to the way I have set the constraints up) the font should be resized or the string split in 2 lines; but not the switch displaced.

Here is the relevant swift code:

import UIKit

class My_ViewController: UIViewController {
    let xPanel = UILabel(), yPanel = UILabel(),
    khToggle = UISwitch(), khLabel = UILabel()
    ....

    override func viewDidLoad() {
        super.viewDidLoad()
        layOutUI()
    }


    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        .....
        toggleKeepHide(khToggle)
    }


    func layOutUI() {
        for component in [xPanel,yPanel,khLabel,khToggle] {
            component.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(component)
        }

        ...........

        khLabel.numberOfLines = 0
        khLabel.adjustsFontSizeToFitWidth = true
        khToggle.addTarget(self,
                                 action: #selector(toggleKeepHide(_:)),
                                 for: .valueChanged)

        view.addConstraints([
            .........
            NSLayoutConstraint(item: khToggle, attribute: .right, relatedBy: .equal,
                               toItem: view, attribute: .right, multiplier: 1.0,    constant: -30.0),
            NSLayoutConstraint(item: khToggle, attribute: .top, relatedBy: .equal,
                               toItem: yPanel, attribute: .bottom, multiplier: 1.0,
                               constant: 50.0),
            NSLayoutConstraint(item: khLabel, attribute: .right, relatedBy: .equal,
                               toItem: khToggle, attribute: .left, multiplier: 1.0,     constant: -23.0),
            NSLayoutConstraint(item: khLabel, attribute: .centerY, relatedBy: .equal,
                               toItem: khToggle, attribute: .centerY, multiplier: 1.0,  constant: 0.0),
            NSLayoutConstraint(item: khLabel, attribute: .left, relatedBy: .equal,
                               toItem: view, attribute: .left, multiplier: 1.0,     constant: 30.0)])
    }


    @objc func toggleKeepHide(_ sender: UISwitch) {
        if sender.isOn {khLabel.text = "Hide this object from the wyxoug list."}
        else {khLabel.text = "Keep this object in the wyxoug list."}
    }
}
Questioner
Michel
Viewed
137
Womble 2019-07-03 20:06

The horizontal constraints for the label and the toggle are competing against each other.

(If you step in to Xcode's visual debugger, you'll find that there is a warning: the UISwitch instance has an ambiguous width and horizontal position.)

enter image description here

Solution

You have provided absolute values to AutoLayout, and it cannot resolve the requirements. To fix this, introduce some flexibility in to the requirements by setting the compression resistance of the label to a lower value:

khLabel.setCompressionResistance(.defaultLow, for: .horizontal)

enter image description here