1

I have a view with two leading constraints that conflict each other. One with leading offset, other without. The 'constant' property works for active constraint. But I want to enable/disable constraints to fit my needs. It works in every place except UITableViewCell, when called from tableView:cellForRowAtIndexPath:. Here is my cell:

class WowCell: UITableViewCell {
    @IBOutlet weak var myView: UIView!
    @IBOutlet var leading: NSLayoutConstraint!
    @IBOutlet var leadingSpace: NSLayoutConstraint!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func setup(ye:Bool) {
        setActiveConstraint(ye: ye)

        //doesn't help
        setNeedsLayout()
        layoutIfNeeded()
        needsUpdateConstraints()
        setNeedsUpdateConstraints()
        needsUpdateConstraints()
        setNeedsLayout()
        setNeedsDisplay()
    }

    func setActiveConstraint(ye:Bool){
        leading.isActive = !ye
        leadingSpace.isActive = ye
    }

    override func layoutSubviews() {
        //when called from here, it does work
    }
}

Thanks in advance

Edit: As Prashant Tukadiya advised, it works by changing priorities of both active constraints. But be aware that both constraint have to be lower than 1000.

func setActiveConstraint(ye:Bool){
    leading.priority  = UILayoutPriority(rawValue: !ye ? 999 : 250)
    leadingSpace.priority = UILayoutPriority(rawValue: ye ? 999 : 250)
}
RealNmae
  • 630
  • 9
  • 20
  • Why don't you change the constant value directly by maintaining single constraint rather than two – Prashant Tukadiya Jun 11 '18 at 10:07
  • @Prashant Tukadiya Because it's not always convenient to compute the constant. This code is just a simplified example. – RealNmae Jun 11 '18 at 10:32
  • what do you mean by not convenient to compute the constant ? Could you pl. add some more info that what you exactly required . there might be other solution – Prashant Tukadiya Jun 11 '18 at 10:34
  • @PrashantTukadiya for me changing priorities to activate/deactivate constraint is a workaround comparing to direct activation/deactivation – derpoliuk Jul 05 '18 at 08:43
  • @derpoliuk That what I have posted as answer – Prashant Tukadiya Jul 05 '18 at 08:55
  • @PrashantTukadiya yes, it looks like workaround for me. I posted the answer where it's possible to directly change `isActive` property to activate/deactivate layout constraint – derpoliuk Jul 05 '18 at 13:02

3 Answers3

1

When you deactive your constraint it will be release by ARC because it's weak property in your vc. You can change by removing weak to handle this.

@IBOutlet var leading: NSLayoutConstraint!
@IBOutlet var leadingSpace: NSLayoutConstraint!

But you need the release them right after they aren't needed if you don't want a memory leak

U. Benlice
  • 901
  • 9
  • 14
0

Try with priority as active / deactivate constraint call addConstraint and removeConstraint internally

func setActiveConstraint(ye:Bool){
    leading.priority  = !ye ? 999 : 250
    leading.priority = ye ? 999 : 250
}
Prashant Tukadiya
  • 15,838
  • 4
  • 62
  • 98
0

There's a way to do that without changing priorities:

  1. Override updateConstraints() in your UITableViewCell
  2. Activate/deactivate constraint there
  3. Make sure to call super.updateConstraints() at the end
derpoliuk
  • 1,756
  • 2
  • 27
  • 43