Skip to content

Commit

Permalink
Transform ibConstraints to global function (#4)
Browse files Browse the repository at this point in the history
* transform ibConstraints from UIView extension to global function, Rename NSLayoutConstraint.activate to NSLayoutConstraint.ibActivate and remove func apply

* Update tests
  • Loading branch information
Adobels authored Oct 9, 2023
1 parent 0c158b8 commit 9fcc87f
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 89 deletions.
19 changes: 0 additions & 19 deletions Sources/UIViewKit/NSObject+Extensions.swift

This file was deleted.

79 changes: 37 additions & 42 deletions Sources/UIViewKit/UIViewDSL+Constraints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,9 @@

import UIKit.NSLayoutConstraint

extension UIView {

public func ibConstraints(to view: UIView, guide: LayoutGuide, anchors: ViewAnchor...) -> [NSLayoutConstraint] {
switch guide {
case .view:
return IBConstraints.generateConstraints(from: self, to: view, anchors: anchors)
case .viewMargins:
return IBConstraints.generateConstraints(from: self, to: view.layoutMarginsGuide, anchors: anchors)
case .viewSafeArea:
return IBConstraints.generateConstraints(from: self, to: view.safeAreaLayoutGuide, anchors: anchors)
}
}
}

extension NSLayoutConstraint {

static public func activate(@NSLayoutConstraintBuilder _ block: () -> [NSLayoutConstraint]) {
static public func ibActivate(@NSLayoutConstraintBuilder _ block: () -> [NSLayoutConstraint]) {
NSLayoutConstraint.activate(block())
}

Expand All @@ -46,36 +32,45 @@ extension NSLayoutConstraint {
}
}

enum IBConstraints {

static func generateConstraints(from view: UIView, to target: Any, anchors: [ViewAnchor]) -> [NSLayoutConstraint] {
var constraints: [NSLayoutConstraint] = []

for anchor in anchors {
switch anchor {
case .left(let value):
constraints.append(view.leftAnchor.constraint(equalTo: (target as? UILayoutGuide)?.leftAnchor ?? (target as! UIView).leftAnchor, constant: value))
case .right(let value):
constraints.append(view.rightAnchor.constraint(equalTo: (target as? UILayoutGuide)?.rightAnchor ?? (target as! UIView).rightAnchor, constant: value))
case .top(let value):
constraints.append(view.topAnchor.constraint(equalTo: (target as? UILayoutGuide)?.topAnchor ?? (target as! UIView).topAnchor, constant: value))
case .bottom(let value):
constraints.append(view.bottomAnchor.constraint(equalTo: (target as? UILayoutGuide)?.bottomAnchor ?? (target as! UIView).bottomAnchor, constant: value))
case .centerX(let value):
constraints.append(view.centerXAnchor.constraint(equalTo: (target as? UILayoutGuide)?.centerXAnchor ?? (target as! UIView).centerXAnchor, constant: value))
case .centerY(let value):
constraints.append(view.centerYAnchor.constraint(equalTo: (target as? UILayoutGuide)?.centerYAnchor ?? (target as! UIView).centerYAnchor, constant: value))
case .leading(let value):
constraints.append(view.leadingAnchor.constraint(equalTo: (target as? UILayoutGuide)?.leadingAnchor ?? (target as! UIView).leadingAnchor, constant: value))
case .trailing(let value):
constraints.append(view.trailingAnchor.constraint(equalTo: (target as? UILayoutGuide)?.trailingAnchor ?? (target as! UIView).trailingAnchor, constant: value))
case .all:
constraints.append(contentsOf: generateConstraints(from: view, to: target, anchors: [.top, .bottom, .left, .right]))
}
public func IBConstraints(from: UIView, to: UIView, guide: LayoutGuide, anchors: ViewAnchor...) -> [NSLayoutConstraint] {
switch guide {
case .view:
return generateConstraints(from: from, to: to, anchors: anchors)
case .viewMargins:
return generateConstraints(from: from, to: to.layoutMarginsGuide, anchors: anchors)
case .viewSafeArea:
return generateConstraints(from: from, to: to.safeAreaLayoutGuide, anchors: anchors)
}
}

func generateConstraints(from view: UIView, to target: Any, anchors: [ViewAnchor]) -> [NSLayoutConstraint] {
var constraints: [NSLayoutConstraint] = []

for anchor in anchors {
switch anchor {
case .left(let value):
constraints.append(view.leftAnchor.constraint(equalTo: (target as? UILayoutGuide)?.leftAnchor ?? (target as! UIView).leftAnchor, constant: value))
case .right(let value):
constraints.append(view.rightAnchor.constraint(equalTo: (target as? UILayoutGuide)?.rightAnchor ?? (target as! UIView).rightAnchor, constant: value))
case .top(let value):
constraints.append(view.topAnchor.constraint(equalTo: (target as? UILayoutGuide)?.topAnchor ?? (target as! UIView).topAnchor, constant: value))
case .bottom(let value):
constraints.append(view.bottomAnchor.constraint(equalTo: (target as? UILayoutGuide)?.bottomAnchor ?? (target as! UIView).bottomAnchor, constant: value))
case .centerX(let value):
constraints.append(view.centerXAnchor.constraint(equalTo: (target as? UILayoutGuide)?.centerXAnchor ?? (target as! UIView).centerXAnchor, constant: value))
case .centerY(let value):
constraints.append(view.centerYAnchor.constraint(equalTo: (target as? UILayoutGuide)?.centerYAnchor ?? (target as! UIView).centerYAnchor, constant: value))
case .leading(let value):
constraints.append(view.leadingAnchor.constraint(equalTo: (target as? UILayoutGuide)?.leadingAnchor ?? (target as! UIView).leadingAnchor, constant: value))
case .trailing(let value):
constraints.append(view.trailingAnchor.constraint(equalTo: (target as? UILayoutGuide)?.trailingAnchor ?? (target as! UIView).trailingAnchor, constant: value))
case .all:
constraints.append(contentsOf: generateConstraints(from: view, to: target, anchors: [.top, .bottom, .left, .right]))
}

return constraints
}

return constraints
}

public enum LayoutGuide {
Expand Down
2 changes: 1 addition & 1 deletion Sources/UIViewKitPreviewsDemo/HelloWordView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class HelloWordView: UIView {
super.init(frame: frame)
self {
UILabel().ibOutlet(&label).ibAttributes {
$0.ibConstraints(to: self, guide: .view, anchors: .centerX, .centerY)
IBConstraints(from: $0, to: self, guide: .view, anchors: .centerX, .centerY)
$0.text = "Hello, world!"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ public class UserTitleTimeDescriptionView: UIView {
var labelTitle: UILabel!
var labelDescription: UILabel!

var totoView: UIView!

override init(frame: CGRect) {
super.init(frame: frame)

self {
HorizontalStack(spacing: 12, alignment: .top) {
UIImageView().ibOutlet(&imageViewUser).ibAttributes {
Expand Down Expand Up @@ -61,7 +62,7 @@ public class UserTitleTimeDescriptionView: UIView {
}
}
}.ibAttributes {
$0.ibConstraints(to: self, guide: .view, anchors: .top, .left(12), .right(-12), .bottom)
IBConstraints(from: $0, to: self, guide: .view, anchors: .top, .left(12), .right(-12), .bottom)
}
}
}
Expand All @@ -76,7 +77,7 @@ import SwiftUI
struct UserTitleTimeDescriptionViewPreviews: PreviewProvider {
static var previews: some View {
ViewPreview(
UserTitleTimeDescriptionView().ibApply {
UserTitleTimeDescriptionView().ibAttributes {
$0.imageViewUser.image = .init(systemName: "person.circle")
$0.labelTitle.text = "Amanda Clarke"
$0.labelTime.text = "1:08 PM"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class UserTitleTimeDescriptionViewWithIBSubviews: UIView {
}
}
}.ibAttributes {
$0.ibConstraints(to: self, guide: .view, anchors: .top, .left(12), .right(-12), .bottom)
IBConstraints(from: $0, to: self, guide: .view, anchors: .top, .left(12), .right(-12), .bottom)
}
}
}
Expand All @@ -76,7 +76,7 @@ import SwiftUI
struct UserTitleTimeDescriptionViewWithIBSubviewsPreviews: PreviewProvider {
static var previews: some View {
ViewPreview(
UserTitleTimeDescriptionViewWithIBSubviews().ibApply {
UserTitleTimeDescriptionViewWithIBSubviews().ibAttributes {
$0.imageViewUser.image = .init(systemName: "person.circle")
$0.labelTitle.text = "Amanda Clarke"
$0.labelTime.text = "1:08 PM"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class UserTitleTimeDescriptionViewWithIBSubviewsWithSuperviewView: UIView
}
}
}.ibAttributes {
$0.ibConstraints(to: self, guide: .view, anchors: .top, .left(12), .right(-12), .bottom)
IBConstraints(from: $0, to: self, guide: .view, anchors: .top, .left(12), .right(-12), .bottom)
}
}
}
Expand All @@ -76,7 +76,7 @@ import SwiftUI
struct UserTitleTimeDescriptionViewWithIBSubviewsWithSuperviewViewPreviews: PreviewProvider {
static var previews: some View {
ViewPreview(
UserTitleTimeDescriptionViewWithIBSubviewsWithSuperviewView().ibApply {
UserTitleTimeDescriptionViewWithIBSubviewsWithSuperviewView().ibAttributes {
$0.imageViewUser.image = .init(systemName: "person.circle")
$0.labelTitle.text = "Amanda Clarke"
$0.labelTime.text = "1:08 PM"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class TestView: UIView {
view2 {
view3.ibAttributes {
$0.tag = 3
$0.ibConstraints(to: self, guide: .view, anchors: .all)
IBConstraints(from: $0, to: self, guide: .view, anchors: .all)
$0.backgroundColor = .green
$0.alpha = 0.3
}
Expand Down
16 changes: 8 additions & 8 deletions Tests/UIViewKitTests/ConstraintsBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,29 @@ class ConstraintsBuilderTests: XCTestCase {
func test() throws {
let view = UIView() { sv in
UIView().ibAttributes {
$0.ibConstraints(to: sv, guide: .view, anchors: .top)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .top)
if true {
$0.ibConstraints(to: sv, guide: .view, anchors: .left)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .left)
} else {
$0.ibConstraints(to: sv, guide: .view, anchors: .left)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .left)
}
if false {
$0.ibConstraints(to: sv, guide: .view, anchors: .right)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .right)
} else {
$0.ibConstraints(to: sv, guide: .view, anchors: .right)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .right)
}
if true {
$0.ibConstraints(to: sv, guide: .view, anchors: .bottom)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .bottom)
}
print()
$0.backgroundColor = .red
}
UIView().ibAttributes {
#if DEBUG
$0.ibConstraints(to: sv, guide: .view, anchors: .top)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .top)
#endif
if let _ = Optional(true) {
$0.ibConstraints(to: sv, guide: .view, anchors: .bottom)
IBConstraints(from: $0, to: sv, guide: .view, anchors: .bottom)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Tests/UIViewKitTests/HelloWorldViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class HelloWorldViewTests: XCTestCase {
let sut = SUT()

let label = try XCTUnwrap(sut.subviews.first! as? UILabel)
XCTAssertEqual(label.superview, sut)
XCTAssertEqual(label.text, "Hello, world!")
XCTAssertEqual(sut.constraints.count, 2)
}

}
18 changes: 9 additions & 9 deletions Tests/UIViewKitTests/IBConstraintsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ class IBConstraintsTests: XCTestCase {

view {
subview.ibAttributes {
$0.ibConstraints(to: view, guide: .view, anchors: .all)
$0.ibConstraints(to: view, guide: .view, anchors: .top, .left, .right, .bottom)
$0.ibConstraints(to: view, guide: .view, anchors: .top(1), .left(1), .right(-1), .bottom(-1))
$0.ibConstraints(to: view, guide: .view, anchors: .top, .leading, .trailing, .bottom)
$0.ibConstraints(to: view, guide: .view, anchors: .top(1), .leading(1), .trailing(-1), .bottom(-1))
$0.ibConstraints(to: view, guide: .view, anchors: .centerX, .centerY)
$0.ibConstraints(to: view, guide: .view, anchors: .centerX(1), .centerY(1))
$0.ibConstraints(to: view, guide: .viewMargins, anchors: .all)
$0.ibConstraints(to: view, guide: .viewSafeArea, anchors: .all)
IBConstraints(from: $0, to: view, guide: .view, anchors: .all)
IBConstraints(from: $0, to: view, guide: .view, anchors: .top, .left, .right, .bottom)
IBConstraints(from: $0, to: view, guide: .view, anchors: .top(1), .left(1), .right(-1), .bottom(-1))
IBConstraints(from: $0, to: view, guide: .view, anchors: .top, .leading, .trailing, .bottom)
IBConstraints(from: $0, to: view, guide: .view, anchors: .top(1), .leading(1), .trailing(-1), .bottom(-1))
IBConstraints(from: $0, to: view, guide: .view, anchors: .centerX, .centerY)
IBConstraints(from: $0, to: view, guide: .view, anchors: .centerX(1), .centerY(1))
IBConstraints(from: $0, to: view, guide: .viewMargins, anchors: .all)
IBConstraints(from: $0, to: view, guide: .viewSafeArea, anchors: .all)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Tests/UIViewKitTests/NSLayoutConstraintTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ class NSLayoutConstraintTests: XCTestCase {
UIView().ibOutlet(&viewSecond)
}

NSLayoutConstraint.activate {
NSLayoutConstraint.ibActivate {
viewFirst.topAnchor.constraint(equalTo: viewSecond.topAnchor).ibOutlet(&constraintTop).ibPriority(.defaultHigh)
viewFirst.leftAnchor.constraint(equalTo: viewSecond.leftAnchor).ibOutlet(&constraintLeft).ibPriority(.defaultLow)
viewFirst.rightAnchor.constraint(equalTo: viewSecond.rightAnchor)
viewFirst.bottomAnchor.constraint(equalTo: viewSecond.bottomAnchor)
}
XCTAssertEqual(view.constraints.count, 4)

XCTAssertEqual(constraintTop.priority, UILayoutPriority.defaultHigh)
XCTAssertEqual(constraintLeft.priority, UILayoutPriority.defaultLow)
Expand Down

0 comments on commit 9fcc87f

Please sign in to comment.