It annoys me a bit that I call NSLayoutConstraint (singular) to generate constraintsWithVisualFormat... (plural), although I'm sure that only I am. In any case, I have two top-level functions:
fragment 1 (Swift 1.2)
#if os(iOS) public typealias View = UIView #elseif os(OSX) public typealias View = NSView #endif public func NSLayoutConstraints(visualFormat: String, options: NSLayoutFormatOptions = .allZeros, views: View...) -> [NSLayoutConstraint] { return NSLayoutConstraints(visualFormat, options: options, views: views) } public func NSLayoutConstraints(visualFormat: String, options: NSLayoutFormatOptions = .allZeros, views: [View] = []) -> [NSLayoutConstraint] { if visualFormat.hasPrefix("B:") { let h = NSLayoutConstraints("H\(dropFirst(visualFormat))", options: options, views: views) let v = NSLayoutConstraints("V\(dropFirst(visualFormat))", options: options, views: views) return h + v } var dict: [String:View] = [:] for (i, v) in enumerate(views) { dict["v\(i + 1)"] = v } let format = visualFormat.stringByReplacingOccurrencesOfString("[v]", withString: "[v1]") return NSLayoutConstraint.constraintsWithVisualFormat(format, options: options, metrics: nil, views: dict) as! [NSLayoutConstraint] }
What can be used like this:
superView.addConstraints(NSLayoutConstraints("B:|[v]|", view))
In other words, the views are automatically called "v1" to "v\(views.count)" (except for the first view, which can also be called "v" ). In addition, with the "B:" format prefix, the restrictions "H:" and "V:" will be generated. Thus, an example line of code means that "make sure that the view always matches the superView ."
And with the following extensions:
fragment 2
public extension View {
We can make some common tasks much more elegant, for example, add a button with a standard offset in the lower right corner:
superView.addSubview(button, constraints: "B:[v]-|")
For example, on an iOS playground:
import UIKit import XCPlayground // paste here `snippet 1` and `snippet 2` let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500)) XCPShowView("view", view) view.backgroundColor = .orangeColor() XCPShowView("view", view) let button = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) button.setTitle("bottom right", forState: .Normal) view.addSubview(button, constraints: "B:[v]-|")