Layout is a DSL for Auto Layout
The DSL allows you to replace this:
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.topAnchor.constraint(
equalTo: button.bottomAnchor,
constant: 10
),
label.leadingAnchor.constraint(
equalTo: button.leadingAnchor
),
label.widthAnchor.constraint(
lessThanOrEqualTo: view.widthAnchor,
constant: -35
),
label.heightAnchor.constraint(
equalToConstant: button.leadingAnchor
)
])
with this:
label.layout {
$0.top == button.bottomAnchor + 10
$0.leading == button.leadingAnchor
$0.width <= view.widthAnchor - 35
$0.height == 40
}
To install Layout, use the Swift Package Manager by declaring Layout as a dependency in your Package.swift
file:
.package(url: "https://github.com/Vutlhari/Layout", from: "0.2.0")
For more information, see the Swift Package Manager documentation.
Call the layout
function on your UIView
instance with a closure in which you declare the constraints between the different attributes of your views:
import Layout
class ViewController: UIViewController {
lazy var box = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(box)
self.box.backgroundColor = .red
self.box.layout {
$0.centerX == self.view.centerXAnchor
$0.centerY == self.view.centerYAnchor
$0.height == 80
$0.width == 80
}
}
}
Layout includes a convenience API that extends UIView
by executing a closure after adding a given view as a subview, like this:
self.view.add(box, then: {
$0.layout {
$0.centerX == self.view.centerXAnchor
$0.centerY == self.view.centerYAnchor
$0.height == 80
$0.width == 80
}
})
Please Note:
Every view on the left hand side of an equality (==
) or inequality (>=
, <=
) operator, Layout will automatically set its translatesAutoresizingMaskIntoConstraints
property to false
.
If the view is not controlled by you – for example if it belongs to a Apple-provided
UIViewController
class – you should take appropriate care when declaring its
constraints.
Layout supports the following iOS attributes:
top
bottom
leading
right
trailing
left
centerX
centerY
width
height
As of version 0.3.0
, Layout now includes some abstractions to get the most out of Xcode’s SwiftUI-powered Previews feature. We can now quickly preview what a UIView
or UIViewController
will look like when rendered in both light and dark mode, using a single PreviewProvider
:
import UIKit
import SwiftUI
import Layout
class SampleView: UIView {
// UI code goes here
}
// The code below is all you need for Xcode to render the Preview
#if DEBUG
@available(iOS 13, *)
struct SampleViewPreview: PreviewProvider {
static var previews: some View {
SampleView().previewAsComponent()
}
}
#endif
import UIKit
import SwiftUI
import Layout
class SampleViewController: UIViewController {
// Controller code goes here
}
// The code below is all you need for Xcode to render the Preview
#if DEBUG
@available(iOS 13, *)
struct SampleViewPreview: PreviewProvider {
static var previews: some View {
SampleViewController().previewAsScreen(on: [
.iPhone11,
.iPad7thGen
])
}
}
#endif
Layout also ships with a preview primitive, .asPreview()
, which works for both UIView
UIViewController
. This gives us more control over how we want to preview our components. For example, we we can use the systemBackground
API on UIColor
to mimic what our component will look like when displayed in dark mode (even if its environment will still remain in light mode):
#if DEBUG
struct TableViewCellPreview: PreviewProvider {
static var previews: some View {
TableViewCell(style: .subtitle, reuseIdentifier: "Cell")
.asPreview()
.background(Color(UIColor.systemBackground))
.colorScheme(.dark)
.environment(\.sizeCategory, .accessibilityLarge)
}
}
#endif
It is recommended to wrap the preview in a DEBUG compiler directive. Doing this will prevent us from accidentally using this type in our production code - the compiler would throw an error when we build our app for release if we did.
Layout is released under the MIT license. See LICENSE for details.