Skip to content

Commit

Permalink
Add support for UIViewController layout guides
Browse files Browse the repository at this point in the history
  • Loading branch information
indragiek committed Jan 9, 2016
1 parent 3e9d219 commit cc28684
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 15 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## SwiftAutoLayout

SwiftAutoLayout is a tiny DSL for Autolayout (~90 LOC), intended to provide a more declarative way to express layout constraints. Here's a quick example:
SwiftAutoLayout is a tiny DSL for Autolayout intended to provide a more declarative way to express layout constraints. Here's a quick example:

```swift
// this:
Expand All @@ -23,6 +23,8 @@ SwiftAutoLayout allows you to more effectively communicate the intent of a const

Layout attributes are defined as properties added in extensions of `UIView` and `UILayoutGuide` on iOS and `NSView` and `NSLayoutGuide` on OS X. For example, `UIView.width` and `UIView.height` represent `NSLayoutAttribute.Width` and `NSLayoutAttribute.Height`, respectively.

Layout guides (conforming to `UILayoutSupport`) in `UIViewController` are also supported using the `topLayoutGuideTop`, `topLayoutGuideBottom`, `bottomLayoutGuideTop`, and `bottomLayoutGuideBottom` properties.

### Relations

Relations are expressed using the overloaded operators `==` (`NSLayoutRelation.Equal`), `>=` (`NSLayoutRelation.GreaterThanOrEqual`), and `<=` (`NSLayoutRelation.LessThanOrEqual`).
Expand Down
46 changes: 33 additions & 13 deletions SwiftAutoLayout/SwiftAutoLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,23 +90,43 @@ public func <=(lhs: LayoutItem<Dimension>, rhs: CGFloat) -> NSLayoutConstraint {
return lhs.constrain(rhs, relation: .LessThanOrEqual)
}

private func layoutItem<C>(item: AnyObject, _ attribute: NSLayoutAttribute) -> LayoutItem<C> {
return LayoutItem(item: item, attribute: attribute, multiplier: 1.0, constant: 0.0)
}

public extension LayoutRegion {
private func layoutItem<C>(attribute: NSLayoutAttribute) -> LayoutItem<C> {
return LayoutItem(item: self, attribute: attribute, multiplier: 1.0, constant: 0.0)
public var left: LayoutItem<XAxis> { return layoutItem(self, .Left) }
public var right: LayoutItem<XAxis> { return layoutItem(self, .Right) }
public var top: LayoutItem<YAxis> { return layoutItem(self, .Top) }
public var bottom: LayoutItem<YAxis> { return layoutItem(self, .Bottom) }
public var leading: LayoutItem<XAxis> { return layoutItem(self, .Leading) }
public var trailing: LayoutItem<XAxis> { return layoutItem(self, .Trailing) }
public var width: LayoutItem<Dimension> { return layoutItem(self, .Width) }
public var height: LayoutItem<Dimension> { return layoutItem(self, .Height) }
public var centerX: LayoutItem<XAxis> { return layoutItem(self, .CenterX) }
public var centerY: LayoutItem<YAxis> { return layoutItem(self, .CenterY) }
public var baseline: LayoutItem<YAxis> { return layoutItem(self, .Baseline) }
}

#if os(iOS)
public extension UIViewController {
public var topLayoutGuideTop: LayoutItem<YAxis> {
return layoutItem(topLayoutGuide, .Top)
}

public var topLayoutGuideBottom: LayoutItem<YAxis> {
return layoutItem(topLayoutGuide, .Bottom)
}

public var bottomLayoutGuideTop: LayoutItem<YAxis> {
return layoutItem(bottomLayoutGuide, .Top)
}

public var left: LayoutItem<XAxis> { return layoutItem(.Left) }
public var right: LayoutItem<XAxis> { return layoutItem(.Right) }
public var top: LayoutItem<YAxis> { return layoutItem(.Top) }
public var bottom: LayoutItem<YAxis> { return layoutItem(.Bottom) }
public var leading: LayoutItem<XAxis> { return layoutItem(.Leading) }
public var trailing: LayoutItem<XAxis> { return layoutItem(.Trailing) }
public var width: LayoutItem<Dimension> { return layoutItem(.Width) }
public var height: LayoutItem<Dimension> { return layoutItem(.Height) }
public var centerX: LayoutItem<XAxis> { return layoutItem(.CenterX) }
public var centerY: LayoutItem<YAxis> { return layoutItem(.CenterY) }
public var baseline: LayoutItem<YAxis> { return layoutItem(.Baseline) }
public var bottomLayoutGuideBottom: LayoutItem<YAxis> {
return layoutItem(bottomLayoutGuide, .Bottom)
}
}
#endif

infix operator ~ { associativity left precedence 120 }

Expand Down
21 changes: 20 additions & 1 deletion SwiftAutoLayoutTests/SwiftAutoLayoutTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@
import XCTest
import SwiftAutoLayout

#if os(iOS)
private class ViewController: UIViewController {
private override func loadView() {
self.view = UIView(frame: CGRectZero)
}
}
#endif

class SwiftAutoLayoutTests: XCTestCase {
let view1 = View(frame: CGRectZero)
let view2 = View(frame: CGRectZero)

func testAttributeValues() {
func testViewAttributeValues() {
XCTAssertEqual(view1.left.attribute, NSLayoutAttribute.Left)
XCTAssertEqual(view1.right.attribute, NSLayoutAttribute.Right)
XCTAssertEqual(view1.top.attribute, NSLayoutAttribute.Top)
Expand All @@ -22,6 +30,17 @@ class SwiftAutoLayoutTests: XCTestCase {
XCTAssertEqual(view1.baseline.attribute, NSLayoutAttribute.Baseline)
}

#if os(iOS)
func testViewControllerAttributeValues() {
let viewController = ViewController()
print(viewController.view) // Load the view
XCTAssertEqual(viewController.topLayoutGuideTop.attribute, NSLayoutAttribute.Top)
XCTAssertEqual(viewController.topLayoutGuideBottom.attribute, NSLayoutAttribute.Bottom)
XCTAssertEqual(viewController.bottomLayoutGuideTop.attribute, NSLayoutAttribute.Top)
XCTAssertEqual(viewController.bottomLayoutGuideBottom.attribute, NSLayoutAttribute.Bottom)
}
#endif

func testEqual() {
let constraint = view1.left == view2.right;
XCTAssertEqual(constraint.firstItem as? View, view1)
Expand Down

0 comments on commit cc28684

Please sign in to comment.