Skip to content

Instantly share code, notes, and snippets.

@marty-suzuki
Last active April 16, 2019 07:33
Show Gist options
  • Save marty-suzuki/79b7a39edfbc17d9dac4ee8cf9ae2091 to your computer and use it in GitHub Desktop.
Save marty-suzuki/79b7a39edfbc17d9dac4ee8cf9ae2091 to your computer and use it in GitHub Desktop.
import UIKit
// - MRAK: Constraint
struct Constraint {
private let _constraint: (UIView, UIView) -> NSLayoutConstraint
init(_ constraint: @escaping (UIView, UIView) -> NSLayoutConstraint) {
self._constraint = constraint
}
func constraint(_ view1: UIView, _ view2: UIView) -> NSLayoutConstraint {
return _constraint(view1, view2)
}
}
extension Constraint {
static func equal<L, Axis>(_ to: KeyPath<UIView, L>, constant: CGFloat = 0, priority: UILayoutPriority? = nil) -> Constraint where L: NSLayoutAnchor<Axis> {
return equal(to, to, constant: constant, priority: priority)
}
static func equal<L, Axis>(_ from: KeyPath<UIView, L>, _ to: KeyPath<UIView, L>, constant: CGFloat = 0, priority: UILayoutPriority? = nil) -> Constraint where L: NSLayoutAnchor<Axis> {
return Constraint({ view1, view2 in
let constraint = view1[keyPath: from].constraint(equalTo: view2[keyPath: to], constant: constant)
if let priority = priority {
constraint.priority = priority
}
return constraint
})
}
}
extension Constraint {
static func equal<L, Axis>(_ to: Anchor<L>, constant: CGFloat = 0, priority: UILayoutPriority? = nil) -> Constraint where L: NSLayoutAnchor<Axis> {
return equal(to, to, constant: constant, priority: priority)
}
static func equal<L, Axis>(_ from: Anchor<L>, _ to: Anchor<L>, constant: CGFloat = 0, priority: UILayoutPriority? = nil) -> Constraint where L: NSLayoutAnchor<Axis> {
return Constraint({ view1, view2 in
let constraint = view1[keyPath: from.keyPath].constraint(equalTo: view2[keyPath: to.keyPath], constant: constant)
if let priority = priority {
constraint.priority = priority
}
return constraint
})
}
}
extension Array where Element == Constraint {
static func edges(_ insets: UIEdgeInsets = .zero, priority: UILayoutPriority? = nil) -> [Constraint] {
return [.equal(\.topAnchor, constant: insets.top, priority: priority),
.equal(\.leftAnchor, constant: insets.left, priority: priority),
.equal(\.rightAnchor, constant: insets.right, priority: priority),
.equal(\.bottomAnchor, constant: insets.bottom, priority: priority)]
}
}
// - MRAK: UIView Extension
extension UIView {
func addSubview(_ subview: UIView, constraints: [Constraint]) {
subview.translatesAutoresizingMaskIntoConstraints = false
addSubview(subview)
addConstraints(constraints.map { $0.constraint(subview, self) })
}
func addConstraint(_ constraint: Constraint, to other: UIView) {
addConstraints([constraint], to: other)
}
func addConstraints(_ constraints: [Constraint], to other: UIView) {
addConstraints(constraints.map { $0.constraint(other, self) })
}
}
// - MARK: - Anchor
protocol AnchorProxy {}
struct Anchor<LayoutAnchor>: AnchorProxy {
let keyPath: KeyPath<UIView, LayoutAnchor>
}
extension AnchorProxy {
static var top: Anchor<NSLayoutYAxisAnchor> {
return .init(keyPath: \.topAnchor)
}
static var bottom: Anchor<NSLayoutYAxisAnchor> {
return .init(keyPath: \.bottomAnchor)
}
static var leading: Anchor<NSLayoutXAxisAnchor> {
return .init(keyPath: \.leadingAnchor)
}
static var trailing: Anchor<NSLayoutXAxisAnchor> {
return .init(keyPath: \.trailingAnchor)
}
}
// - MARK: main
func main() {
let view1 = UIView()
let view2 = UIView()
let view3 = UIView()
view1.addSubview(view2, constraints: .edges())
view1.addSubview(view3, constraints: [.equal(\.topAnchor)])
view1.addSubview(view3, constraints: [.equal(.bottom)])
view2.addConstraints([.equal(\.leftAnchor, \.rightAnchor)], to: view3)
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment