Forked from floriankugler/AutoLayoutHelpers.swift
Last active
January 20, 2022 16:43
-
-
Save Austinate/396b523192b6c22eb5db0664ca97858c to your computer and use it in GitHub Desktop.
Very simple key path based Auto Layout helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
typealias ConstraintBuilder = (_ child: UIView, _ parent: UIView) -> NSLayoutConstraint | |
extension UIView { | |
func addSubview(_ child: UIView, constraints: [ConstraintBuilder]) { | |
addSubview(child) | |
child.translatesAutoresizingMaskIntoConstraints = false | |
NSLayoutConstraint.activate(constraints.map { $0(child, self) }) | |
} | |
@discardableResult | |
func attach<Axis, Anchor>(_ keyPath: KeyPath<UIView, Anchor>, | |
to: KeyPath<UIView, Anchor>, | |
of secondView: UIView, | |
constant: CGFloat = 0, | |
relation: NSLayoutConstraint.Relation) -> NSLayoutConstraint where Anchor: NSLayoutAnchor<Axis> { | |
let builder = attach(keyPath, to, constant: constant, relation: relation) | |
let constraint = builder(self, secondView) | |
constraint.isActive = true | |
return constraint | |
} | |
} | |
func attach<Axis, Anchor>(_ keyPath: KeyPath<UIView, Anchor>, | |
_ to: KeyPath<UIView, Anchor>, | |
constant: CGFloat = 0, | |
relation: NSLayoutConstraint.Relation) -> ConstraintBuilder where Anchor: NSLayoutAnchor<Axis> { | |
return { view, parent in | |
switch relation { | |
case .equal: | |
return view[keyPath: keyPath].constraint(equalTo: parent[keyPath: to], constant: constant) | |
case .greaterThanOrEqual: | |
return view[keyPath: keyPath].constraint(greaterThanOrEqualTo: parent[keyPath: to], constant: constant) | |
case .lessThanOrEqual: | |
return view[keyPath: keyPath].constraint(lessThanOrEqualTo: parent[keyPath: to], constant: constant) | |
@unknown default: | |
fatalError("Unexpected NSLayoutConstraint.Relation case: \(relation)") | |
} | |
} | |
} | |
func attach<Axis, Anchor>(_ keyPath: KeyPath<UIView, Anchor>, | |
constant: CGFloat = 0, | |
relation: NSLayoutConstraint.Relation) -> ConstraintBuilder where Anchor: NSLayoutAnchor<Axis> { | |
return attach(keyPath, keyPath, constant: constant, relation: relation) | |
} | |
func attach<Anchor>(_ keyPath: KeyPath<UIView, Anchor>, | |
constant: CGFloat, | |
relation: NSLayoutConstraint.Relation) -> ConstraintBuilder where Anchor: NSLayoutDimension { | |
return { view1, _ in | |
switch relation { | |
case .equal: | |
return view1[keyPath: keyPath].constraint(equalToConstant: constant) | |
case .lessThanOrEqual: | |
return view1[keyPath: keyPath].constraint(lessThanOrEqualToConstant: constant) | |
case .greaterThanOrEqual: | |
return view1[keyPath: keyPath].constraint(greaterThanOrEqualToConstant: constant) | |
@unknown default: | |
fatalError("Unexpected NSLayoutConstraint.Relation case: \(relation)") | |
} | |
} | |
} | |
let v1 = UIView() | |
v1.backgroundColor = .red | |
v1.frame = CGRect(x: 0, y: 0, width: 200, height: 200) | |
let v2 = UIView() | |
v2.backgroundColor = .green | |
v1.addSubview(v2, constraints: [ | |
attach(\.leadingAnchor, constant: 10, relation: .equal), | |
attach(\.trailingAnchor, constant: -10, relation: .equal), | |
attach(\.heightAnchor, constant: 100, relation: .equal) | |
]) | |
v2.attach(\.topAnchor, to: \.bottomAnchor, of: v1, relation: .equal) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment