'iOS constraints doesn't allow to use multiplier

I am trying to layout some custom views and when I try to activate the constraints, Xcode says that I can't use multiplier. Here is an example of the code:

class MenuView: UIView {

    var addButton: AddButton!
    var settingsButton: SettingsButton!

    // ........

    func setConstraints (withBarReference reference: NSLayoutYAxisAnchor) {
        NSLayoutConstraints.activateConstraints([
             // ........
             addButton.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, multiplier: 0.5),
             // ........
             settingsButton.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, multiplier: 1.5)
        ])
    }

}

The thing here is that Xcode gives a syntax error on the contraintEqualToAnchor: functions and says that I should replace "multiplier" to "constant".

Why can't I use the multiplier option with the X center anchors?



Solution 1:[1]

You can't set multiplier using helper functions, but you can set multiplier using NSLayoutConstraint initializer. Just got stuck by this myself, but found the answer.

Your code: addButton.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, multiplier: 0.5)

Correct code: NSLayoutConstraint(item: addButton, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 0.5, constant: 0)

Also, don't forget to activate this constraint by typing isActive = true

Solution 2:[2]

Previous answers work very weird now.

You can simply create UILayoutGuide with multiplier width/height with view and set guide.trailing equal to the centerX of your subview.

For example, if you need to place the addButton in the first 1/3 of a view and settingsButton in 2/3 you can simply set two layout guides

let addButtonGuide = UILayoutGuide()
self.addLayoutGuide(addButtonGuide)
addButtonGuide.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/3).isActive = true
addButtonGuide.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
addButton.centerXAnchor.constraint(equalTo: addButtonGuide.trailingAnchor).isActive = true

// same for settingsButton but using 2/3 for the multiplier

But the really best way is to use UIStackView and set its distribution property to equalCentering.

Another option is to use uncommon AutoLayout api to create NSLayoutDimension between two centerXAnchor's and make constraint to self.widthAnchor:

addButton.centerXAnchor.anchorWithOffset(to: self.centerXAnchor)
    .constraint(equalTo: self.widthAnchor, multiplier: 0.25).isActive = true

self.centerXAnchor.anchorWithOffset(to: settingsButton.centerXAnchor)
    .constraint(equalTo: self.widthAnchor, multiplier: 0.25).isActive = true

Solution 3:[3]

You can't use multipliers on NSLayoutXAxisAnchor anchors - multiplying by a position along a line doesn't make sense in a way that the constraints system can understand. You can only use multipliers with NSLayoutDimension anchors, which measure lengths, like the width.

The layout you are trying to make would be better achieved using a stack view.

Solution 4:[4]

It seems that in IB you can use the multiplier option with Center X and obtain the effect you're looking for (set the center of button1 at 1/4 the width of the view it's in, and the center of button2 at 2/3 of the width of the view it's in):
setting the center of a button at 1/4 the width of the view it's in, using the Interface Builder. setting the center of a button at 2/3 the width of the view it's in, in StoryBoard

I tried to use it both in code and in IB, and in code I got the same error as you. Surprisingly, in IB it worked, no errors, no warnings. (I am using Xcode 7, will try it in Xcode 8 to see if it still works).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Raimundas Sakalauskas
Solution 2
Solution 3 jrturton
Solution 4