Easier NSLayoutConstraint interactions #2
In a previous post I talked about a new struct (LayoutPriority) and a couple of extension methods on NSLayoutConstraint to ease interacting with them. But, as I later discovered, there is no need for the new struct – we can do the same thing on UILayoutPriority itself. Let's quickly see how.
First, we move all the properties along with the operators to the extension:
extension UILayoutPriority {
static let minNonZero = UILayoutPriority(rawValue: 1)
static let belowDefaultLow = UILayoutPriority(rawValue: UILayoutPriority.defaultLow.rawValue - 1)
static let defaultLow = UILayoutPriority(rawValue: UILayoutPriority.defaultLow.rawValue)
static let aboveDefaultLow = UILayoutPriority(rawValue: UILayoutPriority.defaultLow.rawValue + 1)
static let belowDefaultHigh = UILayoutPriority(rawValue: UILayoutPriority.defaultHigh.rawValue - 1)
static let defaultHigh = UILayoutPriority(rawValue: UILayoutPriority.defaultHigh.rawValue)
static let aboveDefaultHigh = UILayoutPriority(rawValue: UILayoutPriority.defaultHigh.rawValue + 1)
static let maxNonRequired = UILayoutPriority(rawValue: UILayoutPriority.required.rawValue - 1)
}
extension UILayoutPriority {
static func -(lhs: UILayoutPriority, rhs: Float) -> UILayoutPriority {
return UILayoutPriority(rawValue: lhs.rawValue - rhs)
}
static func +(lhs: UILayoutPriority, rhs: Float) -> UILayoutPriority {
return UILayoutPriority(rawValue: lhs.rawValue + rhs)
}
static func -=(lhs: inout UILayoutPriority, rhs: Float) {
lhs = UILayoutPriority(rawValue: lhs.rawValue - rhs)
}
}Finally, we just have to update the methods in NSLayoutConstraint's extension:
extension NSLayoutConstraint {
func with(priority: UILayoutPriority) -> NSLayoutConstraint {
self.priority = priority
return self
}
}Now we have the same functionality as before, without the need of an extra type; and we get to keep the same short syntax, chaining and operators:
someView.leadingAnchor
.constraint(equalTo: otherView.leadingAnchor)
.with(priority: .defaultHigh - 1)
.activate()The other advantage to this approach is that setContentCompressionResistancePriority:for: and setContentHuggingPriority:for: are using UILayoutPriority, so we can now pass our new constants, instead of creating new methods for those, or bridging LayoutPriority to UIKit:
// Built-in
let priority = UILayoutPriority(rawValue: UILayoutPriority.defaultLow.rawValue - 1)
view.setContentCompressionResistancePriority(priority, for: .vertical)
// Previous
view.setContentCompressionResistancePriority(LayoutPriority.belowDefaultLow.toUIKit, for: .vertical)
// New
view.setContentCompressionResistancePriority(.belowDefaultLow, for: .vertical)In hindsight, I have no idea why I went that route, instead of this one.