AnchorsBuilder is a DSL builder for Anchors types that aids in the creation of autolayout constraints between views.
It is mainly used within anchors, a method of Layout.
Anchors
Anchors have attributes for NSLayoutConstraint and can creates.
The Layout types created with LayoutBuilder and AnchorsBuilder only contain information to actually work. For the application of addSubview and constraint, the method below must be called:
you can call finalActive of Layout for instantly do all stuff in case of no needs to updates.
finalActive return nothing after addSubview and active constraints instantly.
In SwiftLayout, Layoutable plays a role similar to that of View in SwiftUI.
For implementing Layoutable, you needs be write following codes
var activation: Activation?
@LayoutBuilder var layout: some Layout { ... }: @LayoutBuilder may not required.
class SomeView: UIView, Layoutable {
var activation: Activation?
@LayoutBuilder var layout: some Layout {
self.sublayout {
...
}
}
init(frame: CGRect) {
super.init(frame: frame)
self.sl.updateLayout() // call active or update of Layout
}
}
LayoutProperty
Builders of SwiftLayout is DSL languages, so you can perform if, switch case, for etc.
However, in order to reflect the state change in the layout of the view, you must directly call the updateLayout method of the sl property provided by Layoutable when necessary.
var showMiddleName: Bool = false {
didSet {
self.sl.updateLayout()
}
}
var layout: some Layout {
self.sublayout {
firstNameLabel
if showMiddleName {
middleNameLabel
}
lastNameLabel
}
}
If showMiddleName is false, middleNameLabel is not added to the super view, and if it is already added, it is removed from the super view.
In this case, you can update automatically by using LayoutProperty:
@LayoutProeprty var showMiddleName: Bool = false // change value call updateLayout of Layoutable
var layout: some Layout {
self.sublayout {
firstNameLabel
if showMiddleName {
middleNameLabel
}
lastNameLabel
}
}
Animations
You can start animation by updating constraint in Layoutable, And the method is as easy as the following
in the animation block of UIView, call updateLayout with forceLayout parameter set to true.
final class PreviewView: UIView, Layoutable {
var capTop = true {
didSet {
// start animation for change constraints
UIView.animate(withDuration: 1.0) {
self.sl.updateLayout(forceLayout: true)
}
}
}
// or just use the convenient propertyWrapper like below
// @AnimatableLayoutProperty(duration: 1.0) var capTop = true
let cap = UIButton()
let shoe = UIButton()
let title = UILabel()
var top: UIButton { capTop ? cap : shoe }
var bottom: UIButton { capTop ? shoe : cap }
var activation: Activation?
var layout: some Layout {
self.sublayout {
top.anchors {
Anchors.cap()
}
bottom.anchors {
Anchors.top.equalTo(top.bottomAnchor)
Anchors.height.equalTo(top)
Anchors.shoe()
}
title.config { label in
label.text = "Top Title"
UIView.transition(with: label, duration: 1.0, options: [.beginFromCurrentState, .transitionCrossDissolve]) {
label.textColor = self.capTop ? .black : .yellow
}
}.anchors {
Anchors.center(top)
}
UILabel().config { label in
label.text = "Bottom Title"
label.textColor = capTop ? .yellow : .black
}.identifying("title.bottom").anchors {
Anchors.center(bottom)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
initViews()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initViews()
}
func initViews() {
cap.backgroundColor = .yellow
shoe.backgroundColor = .black
cap.addAction(.init(handler: { [weak self] _ in
self?.capTop.toggle()
}), for: .touchUpInside)
shoe.addAction(.init(handler: { [weak self] _ in
self?.capTop.toggle()
}), for: .touchUpInside)
self.accessibilityIdentifier = "root"
updateIdentifiers(rootObject: self)
self.sl.updateLayout()
}
}
Other useful features
config(_:) of UIView
You can decorate view in Layout with config function (and using outside freely)
This can be useful when you want to migrate your current view to SwiftLayout for several reasons.
printing UIView hierarchy and autolayout constraint relationship to SwiftLayout syntax
let contentView: UIView
let firstNameLabel: UILabel
contentView.addSubview(firstNameLabel)
you can use ViewPrinter in source or debug console.
(lldb) po import SwiftLayoutUtil; ViewPrinter(contentView).print()
// If there is no separate identification setting, the view is displayed in the form of addressValue:View type.
0x01234567890:UIView {
0x01234567891:UILabel
}
printing labels for view by name of view property is very convenient.
class SomeView {
let root: UIView // subview of SomeView
let child: UIView // subview of root
let friend: UIView // subview of root
}
let someView = SomeView()
(lldb) po import SwiftLayoutUtil; ViewPrinter(someView, tags: [someView: “SomeView”]).updateIdentifiers().print()
Yesterday never dies
A swifty way to use UIKit
Translation
Requirements
iOS 13+
Installation
SwiftLayout only supports deployments via SPM(Swift Package Manager).
Features
addSubviewandremoveFromSuperviewNSLayoutConstraint,NSLayoutAnchorand activationif else,swift case,forin view hierarhcy and autolayout constraints.Usage
LayoutBuilder
LayoutBuilderis a DSL builder for setting up the UIView hierarchy; this allows subviews to be added to the parent view in a simple and visible way.this is like below:
AnchorsBuilder
AnchorsBuilderis a DSL builder forAnchorstypes that aids in the creation of autolayout constraints between views. It is mainly used withinanchors, a method of Layout.Anchors
Anchorshave attributes for NSLayoutConstraint and can creates.It starts by getting the required properties using static values defined in Anchors.
You can set up a second item (NSLayoutConstraint.secondItem, secondAttribute) through a relationship method such as equalTo.
this is same as following constraint format:
Attributes in Anchors that do not have a relation function in the child can be configured to match the parent item
this can be expressed by the following expression:
also, the constraint and multiplier can be set as follows.
Width and height become the item itself if you do not set the second item.
this represents the following expression.
LayoutBuilder + AnchorsBuilder
ah, finally
LayoutBuilderandAnchorsBuildercan now be used together to add subviews, create autolayouts, and apply them to views.A
sublayoutmethod is required to add subviews after invoking ananchorsmethod.Is your hierarchy too complex? Just separates it.
active and finalActive
The
Layouttypes created withLayoutBuilderandAnchorsBuilderonly contain information to actually work.For the application of addSubview and constraint, the method below must be called:
you can call
finalActiveofLayoutfor instantly do all stuff in case of no needs to updates.finalActivereturn nothing after addSubview and active constraints instantly.you can call
activeofLayoutif needs using some features for updates.Returns
Activation, an object containing information needed for update.Layoutable
In SwiftLayout,
Layoutableplays a role similar to that ofViewin SwiftUI.For implementing
Layoutable, you needs be write following codesvar activation: Activation?@LayoutBuilder var layout: some Layout { ... }: @LayoutBuilder may not required.LayoutProperty
Builders of SwiftLayout is DSL languages, so you can perform if, switch case, for etc.
However, in order to reflect the state change in the layout of the view, you must directly call the
updateLayoutmethod of theslproperty provided byLayoutablewhen necessary.If
showMiddleNameis false,middleNameLabelis not added to the super view, and if it is already added, it is removed from the super view.In this case, you can update automatically by using
LayoutProperty:Animations
You can start animation by updating constraint in
Layoutable, And the method is as easy as the followingUIView, callupdateLayoutwithforceLayoutparameter set to true.Other useful features
config(_:)of UIViewYou can decorate view in Layout with config function (and using outside freely)
identifyingofUIViewandLayoutYou can set
accessibilityIdentifierand use that instead of the view reference.Using in
SwiftUIimplement
LayoutableonUIVieworUIViewControlleryou can easily using it inSwiftUI.SwiftLayoutUtil
LayoutPrinter
This can be useful when you want to make sure the current layout is configured the way you want it to.
prints the tree created by the hierarchy of layouts and anchors.
you can use LayoutPrinter in source or debug console.
if necessary, you can also print Anchors applied to the layout.
ViewPrinter
This can be useful when you want to migrate your current view to SwiftLayout for several reasons.
printing UIView hierarchy and autolayout constraint relationship to SwiftLayout syntax
you can use ViewPrinter in source or debug console.
printing labels for view by name of view property is very convenient.
Credits