Skip to content

Instantly share code, notes, and snippets.

@danyowdee
Last active August 29, 2015 14:24
Show Gist options
  • Save danyowdee/0b7a44256582ce7703dc to your computer and use it in GitHub Desktop.
Save danyowdee/0b7a44256582ce7703dc to your computer and use it in GitHub Desktop.
//
// Anchor.swift
// AnchorTest
//
// Created by Jonathan Wight on 7/10/15.
// Copyright © 2015 schwa.io. All rights reserved.
//
#if os(OSX)
import AppKit
internal typealias View = NSView
#elseif os(iOS)
import UIKit
internal typealias View = UIView
#endif
public extension View {
@objc(d12_anchors)
var anchors: Anchors {
return Anchors(item:self)
}
}
/// Generator for the actual anchors in a way that makes sense, semantically.
@objc(D12Anchors)
public class Anchors {
internal let item: View
internal init(item: View) {
self.item = item
}
// MARK: X–Axis Anchors
public var leadingAnchor: LayoutXAxisAnchor {
return LayoutXAxisAnchor(item: item, attribute: .Leading)
}
public var trailingAnchor: LayoutXAxisAnchor {
return LayoutXAxisAnchor(item: item, attribute: .Trailing)
}
public var leftAnchor: LayoutXAxisAnchor {
return LayoutXAxisAnchor(item: item, attribute: .Left)
}
public var rightAnchor: LayoutXAxisAnchor {
return LayoutXAxisAnchor(item: item, attribute: .Right)
}
public var centerXAnchor: LayoutXAxisAnchor {
return LayoutXAxisAnchor(item: item, attribute: .CenterX)
}
// MARK: Y–Axis Anchors
public var topAnchor: LayoutYAxisAnchor {
return LayoutYAxisAnchor(item: item, attribute: .Top)
}
public var bottomAnchor: LayoutYAxisAnchor {
return LayoutYAxisAnchor(item: item, attribute: .Bottom)
}
public var centerYAnchor: LayoutYAxisAnchor {
return LayoutYAxisAnchor(item: item, attribute: .CenterY)
}
public var firstBaselineAnchor: LayoutYAxisAnchor {
return LayoutYAxisAnchor(item: item, attribute: .FirstBaseline)
}
public var lastBaselineAnchor: LayoutYAxisAnchor {
return LayoutYAxisAnchor(item: item, attribute: .LastBaseline)
}
// MARK: Size Anchors
public var widthAnchor: LayoutDimension {
return LayoutDimension(item: item, attribute: .Width)
}
public var heightAnchor: LayoutDimension {
return LayoutDimension(item: item, attribute: .Height)
}
}
// MARK: -
/**
A LayoutAnchor represents an edge or dimension of a layout item.
Its concrete subclasses allow concise creation of constraints.
The idea is that instead of invoking
+[NSLayoutConstraint constraintWithItem: attribute: relatedBy: toItem: attribute: multiplier: constant:]
directly, you can instead do something like this:
[myView.topAnchor constraintEqualToAnchor:otherView.topAnchor constant:10];
The `-constraint*` methods are available in multiple flavors to support use of different relations and omission of unused options.
*/
@objc(D12LayoutAnchor)
public class LayoutAnchor {
internal var item: View
internal var attribute: NSLayoutAttribute
internal init(item: View, attribute: NSLayoutAttribute) {
self.item = item
self.attribute = attribute
}
/// Returns a new, inactive constraint of the form thisAnchor = otherAnchor + constant.
public func constraintEqualToAnchor(anchor: LayoutAnchor, constant c: CGFloat = 0) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .Equal, toItem: anchor.item, attribute: anchor.attribute, multiplier: 1.0, constant: c)
}
/// Returns a new, inactive constraint of the form thisAnchor ≧ otherAnchor + constant.
public func constraintGreaterThanOrEqualToAnchor(anchor: LayoutAnchor, constant c: CGFloat = 0) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .GreaterThanOrEqual, toItem: anchor.item, attribute: anchor.attribute, multiplier: 1.0, constant: c)
}
/// Returns a new, inactive constraint of the form thisAnchor ≦ otherAnchor + constant.
public func constraintLessThanOrEqualToAnchor(anchor: LayoutAnchor, constant c: CGFloat = 0) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .LessThanOrEqual, toItem: anchor.item, attribute: anchor.attribute, multiplier: 1.0, constant: c)
}
}
// MARK: - Axis-specific subclasses for location anchors
/// Subclass for leading/trailing, left/right, and centerX anchors.
@objc(D12LayoutXAxisAnchor)
public class LayoutXAxisAnchor : LayoutAnchor {
}
/// Subclass for top/bottom, firstBaseline/lastBaseLine, and centerY anchors
@objc(D12LayoutYAxisAnchor)
public class LayoutYAxisAnchor : LayoutAnchor {
}
// MARK: -
/**
This layout anchor subclass is used for sizes (width & height).
*/
@objc(D12LayoutDimension)
public class LayoutDimension : LayoutAnchor {
/// Returns a new, inactive constraint of the form attribute = constant.
public func constraintEqualToConstant(c: CGFloat) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .Equal, toItem: nil, attribute:.NotAnAttribute, multiplier: 1.0, constant: c)
}
/// Returns a new, inactive constraint of the form attribute ≧ constant.
public func constraintGreaterThanOrEqualToConstant(c: CGFloat) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .GreaterThanOrEqual, toItem: nil, attribute:.NotAnAttribute, multiplier: 1.0, constant: c)
}
/// Returns a new, inactive constraint of the form attribute ≦ constant.
public func constraintLessThanOrEqualToConstant(c: CGFloat) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .LessThanOrEqual, toItem: nil, attribute:.NotAnAttribute, multiplier: 1.0, constant: c)
}
/// Returns a new, inactive constraint of the form attribute = otherAnchor.attribute * multiplier + constant.
public func constraintEqualToAnchor(anchor: LayoutDimension, multiplier m: CGFloat, constant c: CGFloat = 0) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .Equal, toItem: anchor.item, attribute: anchor.attribute, multiplier: m, constant: c)
}
/// Returns a new, inactive constraint of the form attribute ≧ otherAnchor.attribute * multiplier + constant.
public func constraintGreaterThanOrEqualToAnchor(anchor: LayoutDimension, multiplier m: CGFloat, constant c: CGFloat = 0) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .GreaterThanOrEqual, toItem: anchor.item, attribute: anchor.attribute, multiplier: m, constant: c)
}
/// Returns a new, inactive constraint of the form attribute ≦ otherAnchor.attribute * multiplier + constant.
public func constraintLessThanOrEqualToAnchor(anchor: LayoutDimension, multiplier m: CGFloat, constant c: CGFloat = 0) -> NSLayoutConstraint {
return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .LessThanOrEqual, toItem: anchor.item, attribute: anchor.attribute, multiplier: m, constant: c)
}
}
@danyowdee
Copy link
Author

I hope it goes without saying that this is completely untested: the changes I made to the original were written in GitHub’s online editor.
While most are of cosmetic nature — documentation comments and whitespace — I am not really sure if replacing the duplicated methods by default parameters was a smart move in terms of ObjC compatibility. So I’m not sure if they make it over to Objective–C as two separate methods. (So far, every piece of Swift I wrote didn’t need to be callable by ObjC code.) And I don’t have Xcode on this machine to test that out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment