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.