Cannot pass immutable value of type 'NSLayoutConstraint' as inout argument
Asked Answered
T

1

6

I try to reassign an referecend NSLayoutConstraint.

class ViewController: UIViewController {
    @IBOutlet weak var myConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        exchangeConstraint(&myConstraint)
    }
}

extension UIViewController {
    func exchangeConstraint(_ constraint: inout NSLayoutConstraint) {
        let spacing = constraint.constant
        view.removeConstraint(constraint)
        constraint = view.topAnchor.constraint(equalTo: anotherView.topAnchor, constant: spacing)
        view.addConstraint(constraint)
    }
}

But here it gives me the error:

exchangeConstraint(&myConstraint)
-------------------^
Cannot pass immutable value of type 'NSLayoutConstraint' as inout argument

What i don't understand is why it says immutable value, whereas the constraint is declared as a variable, not a constant.

Thibault answered 6/12, 2017 at 9:1 Comment(8)
Constraints don't work like that. You need to remove the old constraint and install a new one (you can modify the constant property but you don't need an inout parameter for that). You should have a very good reason to use inout parameters anyway. It is better for the function to return a new constraint if that is what you want.Knotweed
yes, currently to keep my code running i do it as you suggest. so myConstraint = doSomething(myConstraint). I just don't like using the variable two times in a line for one thing. I hope for a cleaner way.Aerobic
That is the cleaner way compared to using a side effect (inout parameter). As I said, you need to remove the existing constraint anyway before you add a new one, if you don't have the reference to the exisiting constraint, it will be hard to do that.Knotweed
NSLayoutConstraint is reference type anyway. Why do you pass it as an inout parameter?Hearts
Ok, i updated my example. I want to keep the constraint variable, but change its content. So i remove it from the view, assign a new value to the variable and add it again.Aerobic
Not before a computer, so I can‘t check. But I suspect this is because the var is an implicitly unwrapped optional. Does something change if you declare the constraint explicitely optional?Coolidge
To elaborate, easiest would probably be to change the parameter type of the exchangeConstraint func so it takes an optional. This should get rid of the implicit unwrapCoolidge
Or you could call it as exchangeConstraint(&myConstraint!)myConstraint! produces an l-value that can be used with inout.Anaphrodisiac
T
1

I solved it by simply declaring the constraint parameter as an explicitly unwraped NSLayoutConstraint.

func exchangeConstraint(_ constraint: inout NSLayoutConstraint!) {
    ...
}

UPDATE

Here is a project where I use it: https://github.com/truffls/compatible-layout-anchors-ios

Thibault answered 7/12, 2017 at 12:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.