Skip to content

Commit

Permalink
Fix LayoutGuide conformance
Browse files Browse the repository at this point in the history
  • Loading branch information
PimCoumans committed Mar 1, 2023
1 parent 973579d commit 589fa8f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
16 changes: 13 additions & 3 deletions Sources/ConstraintBuilder/ConstraintBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import UIKit
public typealias LayoutPriority = UILayoutPriority
public typealias LayoutGuide = UILayoutGuide
extension UILayoutGuide: LayoutContainer { }
extension UIView: LayoutContainerView { }
#elseif canImport(AppKit)
import AppKit
public typealias LayoutPriority = NSLayoutConstraint.Priority
public typealias LayoutGuide = NSLayoutGuide
extension NSLayoutGuide: LayoutContainer { }
extension NSView: LayoutContainerView { }
#endif

Expand All @@ -24,8 +26,6 @@ public protocol LayoutContainer {
var centerYAnchor: NSLayoutYAxisAnchor { get }
}

extension LayoutGuide: LayoutContainer { }

// Layout guides available in NSView (from macOS 11.0) and UIView (from iOS 11.0)
public protocol LayoutContainerView: LayoutContainer {
@available(macOS 11.0, iOS 11.0, tvOS 11.0, *)
Expand All @@ -44,6 +44,7 @@ public struct ConstraintBuilder {
}
}

/// Convenience methods to apply layout constraints
public protocol ConstraintBuildable {
associatedtype Constrained: LayoutContainer
/// Create and activate constraints with this view as the main subject
Expand Down Expand Up @@ -72,6 +73,14 @@ public protocol ConstraintBuildable {
func aspectFit(in other: any LayoutContainer) -> NSLayoutConstraint
}

// Conformance to `ConstraintBuildable` for `NSLayoutGuide` and `UILayoutGuide`
extension LayoutGuide: ConstraintBuildable {
public func applyConstraints(_ builder: (LayoutGuide) -> [NSLayoutConstraint]) {
NSLayoutConstraint.activate(builder(self))
}
}

/// Convenience methods to apply layout constraints to views
public protocol ViewConstraintBuildable: ConstraintBuildable where Constrained: LayoutContainerView {
/// Use superview if available, `assertionFailure()` if not
func withSuperview(_ method: (Constrained) -> Void)
Expand All @@ -95,6 +104,7 @@ public protocol ViewConstraintBuildable: ConstraintBuildable where Constrained:
func extendToSuperviewLayoutMargins()
}

// Default implementations of convenience methods
extension ConstraintBuildable where Self: LayoutContainer {
public func extend(to other: any LayoutContainer) {
applyConstraints { _ in
Expand Down Expand Up @@ -133,7 +143,7 @@ extension ConstraintBuildable where Self: LayoutContainer {
return aspectRatioConstraint
}
}

// Default implementations of view convenience methods
extension ViewConstraintBuildable where Self: LayoutContainerView {
public func extendToSuperview() {
withSuperview(extend(to:))
Expand Down
13 changes: 13 additions & 0 deletions Tests/ConstraintBuilderTests/ConstraintBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,33 @@ final class ConstraintBuilderTests: XCTestCase {
#if canImport(UIKit) || canImport(tvOS)
var superview: UIView!
var view: UIView!
var guide: UILayoutGuide!
#elseif canImport(AppKit)
var superview: NSView!
var view: NSView!
var guide: NSLayoutGuide!
#endif
override func setUp() {
#if canImport(UIKit) || canImport(tvOS)
superview = UIView()
view = UIView()
guide = UILayoutGuide()
#elseif canImport(AppKit)
superview = NSView()
view = NSView()
guide = NSLayoutGuide()
#endif
superview.addLayoutGuide(guide)
superview.addSubview(view)
}

func testGuideExtendToView() {
guide.extend(to: superview)
}

func testViewExtendToGuide() {
view.extend(to: guide)
}

func testExtendToSuperview() {
view.extendToSuperview()
Expand Down

0 comments on commit 589fa8f

Please sign in to comment.