From f7133e622d7d6c4c56648a6c654143e64bf64a5b Mon Sep 17 00:00:00 2001 From: Pim Date: Mon, 7 Nov 2022 17:18:51 +0100 Subject: [PATCH] Add support for collections and layout guides --- .../ConstraintBuilder/ConstraintBuilder.swift | 24 ++++++----- .../UILayoutGuide+ConstraintBuildable.swift | 26 ++++++++++++ .../UIView+ConstraintBuildable.swift | 40 ++++++++++--------- 3 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 Sources/ConstraintBuilder/UILayoutGuide+ConstraintBuildable.swift diff --git a/Sources/ConstraintBuilder/ConstraintBuilder.swift b/Sources/ConstraintBuilder/ConstraintBuilder.swift index 129cbe8..063fd5d 100644 --- a/Sources/ConstraintBuilder/ConstraintBuilder.swift +++ b/Sources/ConstraintBuilder/ConstraintBuilder.swift @@ -32,20 +32,22 @@ public extension NSLayoutConstraint { } } -public protocol ContraintBuildable { +public protocol ConstraintBuildable { + associatedtype Constrained + /// Create and activate constraints with this view as the main subject + /// ```swift + /// view.applyConstraints { + /// $0.leadingAnchor.constraint(equalTo: otherView.leadingAnchor) + /// $0.centerYAnchor.constraint(equalTo: otherView.centerYAnchor) + /// } + /// ``` + /// - Parameter builder: Constraint builder to add the constraints from + func applyConstraints(@ConstraintBuilder _ builder: (Constrained) -> [NSLayoutConstraint]) /// Extends all edges to the edges of the provided view /// - Parameter view: View of which edges should be extended to - func extend(to view: Self) + func extend(to other: Constrained) /// Aligns center with center of provided view /// - Parameter view: View of which center should be aligned to - func center(in view: Self) - - /// Extends all edges to the edges of the superview - /// Should result in `assertionFailure` when no superview is available - func extendToSuperview() - - /// Aligns center with center of superview - /// Should result in `assertionFailure` when no superview is available - func centerInSuperview() + func center(in other: Constrained) } diff --git a/Sources/ConstraintBuilder/UILayoutGuide+ConstraintBuildable.swift b/Sources/ConstraintBuilder/UILayoutGuide+ConstraintBuildable.swift new file mode 100644 index 0000000..142ecf8 --- /dev/null +++ b/Sources/ConstraintBuilder/UILayoutGuide+ConstraintBuildable.swift @@ -0,0 +1,26 @@ +#if canImport(UIKit) +import UIKit + +extension UILayoutGuide: ConstraintBuildable { + public func applyConstraints(@ConstraintBuilder _ builder: (UILayoutGuide) -> [NSLayoutConstraint]) { + NSLayoutConstraint.activate(builder(self)) + } + + public func extend(to other: UILayoutGuide) { + applyConstraints { _ in + leadingAnchor.constraint(equalTo: other.leadingAnchor) + trailingAnchor.constraint(equalTo: other.trailingAnchor) + topAnchor.constraint(equalTo: other.topAnchor) + bottomAnchor.constraint(equalTo: other.bottomAnchor) + } + } + + public func center(in other: UILayoutGuide) { + applyConstraints { _ in + centerXAnchor.constraint(equalTo: other.centerXAnchor) + centerYAnchor.constraint(equalTo: other.centerYAnchor) + } + } +} + +#endif diff --git a/Sources/ConstraintBuilder/UIView+ConstraintBuildable.swift b/Sources/ConstraintBuilder/UIView+ConstraintBuildable.swift index 5fea539..a1a83fc 100644 --- a/Sources/ConstraintBuilder/UIView+ConstraintBuildable.swift +++ b/Sources/ConstraintBuilder/UIView+ConstraintBuildable.swift @@ -1,16 +1,20 @@ #if canImport(UIKit) import UIKit -public protocol UIViewConstraintBuildable: ContraintBuildable { - /// Create and activate constriants with this view as the main subject - /// ```swift - /// view.applyConstraints { - /// $0.leadingAnchor.constraint(equalTo: otherView.leadingAnchor) - /// $0.centerYAnchor.constraint(equalTo: otherView.centerYAnchor) - /// } - /// ``` - /// - Parameter builder: Constraint builder to add the constriants from - func applyConstraints(@ConstraintBuilder _ builder: (UIView) -> [NSLayoutConstraint]) +extension Collection where Element: ConstraintBuildable { + public func applyConstraints(@ConstraintBuilder _ builder: (Element) -> [NSLayoutConstraint]) { + NSLayoutConstraint.activate(flatMap { builder($0) }) + } +} + +public protocol UIViewConstraintBuildable: ConstraintBuildable { + /// Extends all edges to the edges of the superview + /// Should result in `assertionFailure` when no superview is available + func extendToSuperview() + + /// Aligns center with center of superview + /// Should result in `assertionFailure` when no superview is available + func centerInSuperview() /// Extends all edges to provided layout guide /// - Parameter view: UILayoutGuide of which edges should be extended to @@ -35,19 +39,19 @@ extension UIView: UIViewConstraintBuildable { NSLayoutConstraint.activate(builder(self)) } - public func extend(to view: UIView) { + public func extend(to other: UIView) { applyConstraints { _ in - leadingAnchor.constraint(equalTo: view.leadingAnchor) - trailingAnchor.constraint(equalTo: view.trailingAnchor) - topAnchor.constraint(equalTo: view.topAnchor) - bottomAnchor.constraint(equalTo: view.bottomAnchor) + leadingAnchor.constraint(equalTo: other.leadingAnchor) + trailingAnchor.constraint(equalTo: other.trailingAnchor) + topAnchor.constraint(equalTo: other.topAnchor) + bottomAnchor.constraint(equalTo: other.bottomAnchor) } } - public func center(in view: UIView) { + public func center(in other: UIView) { applyConstraints { _ in - centerXAnchor.constraint(equalTo: view.centerXAnchor) - centerYAnchor.constraint(equalTo: view.centerYAnchor) + centerXAnchor.constraint(equalTo: other.centerXAnchor) + centerYAnchor.constraint(equalTo: other.centerYAnchor) } }