Skip to content

Instantly share code, notes, and snippets.

@zhigang1992
Created September 22, 2016 19:03
Show Gist options
  • Save zhigang1992/4247751d4e09c5884d9fd5abcd393ca7 to your computer and use it in GitHub Desktop.
Save zhigang1992/4247751d4e09c5884d9fd5abcd393ca7 to your computer and use it in GitHub Desktop.
import UIKit
precedencegroup PipingPrecedence {
associativity: left
higherThan: LogicalConjunctionPrecedence
}
infix operator |> : PipingPrecedence
func |><A,B>(a:A, function: (A)->B) -> B {
return function(a)
}
struct ConstraintConfig {
let relation: NSLayoutRelation
let constant: CGFloat
let priority: UILayoutPriority
let activate: Bool
init (
relation: NSLayoutRelation = .equal,
constant: CGFloat = 0.0,
priority: UILayoutPriority = UILayoutPriorityRequired,
activate: Bool = true
) {
self.relation = relation
self.constant = constant
self.priority = priority
self.activate = activate
}
static let defaultConfig = ConstraintConfig()
func config(constraint: NSLayoutConstraint) -> NSLayoutConstraint {
constraint.constant = self.constant
constraint.priority = self.priority
constraint.isActive = self.activate
return constraint
}
}
struct Edge {
static let top: (UIView) -> NSLayoutYAxisAnchor = { $0.topAnchor }
static let bottom: (UIView) -> NSLayoutYAxisAnchor = { $0.bottomAnchor }
static let leading: (UIView) -> NSLayoutXAxisAnchor = { $0.leadingAnchor }
static let trailing: (UIView) -> NSLayoutXAxisAnchor = { $0.trailingAnchor }
static let centerX: (UIView) -> NSLayoutXAxisAnchor = { $0.centerXAnchor }
static let centerY: (UIView) -> NSLayoutYAxisAnchor = { $0.centerYAnchor }
static let topGuide: (UIViewController) -> NSLayoutYAxisAnchor = {
$0.topLayoutGuide.bottomAnchor
}
static let width: (UIView) -> NSLayoutDimension = { $0.widthAnchor }
static let height: (UIView) -> NSLayoutDimension = { $0.heightAnchor }
}
enum EdgeToPin {
case leading(ConstraintConfig)
case trailing(ConstraintConfig)
case top(ConstraintConfig)
case bottom(ConstraintConfig)
static let all:[EdgeToPin] = [
.leading(.defaultConfig),
.trailing(.defaultConfig),
.top(.defaultConfig),
.bottom(.defaultConfig)
]
}
struct AnchorMan {
static func pin<U, V, T: AnyObject>(
anchor: (U) -> NSLayoutAnchor<T>,
ofItem item: U,
toAnchor: (V) -> NSLayoutAnchor<T>,
ofOtherItem otherItem: V,
config: ConstraintConfig
) -> NSLayoutConstraint {
let fromAnchor = anchor(item)
let toAnchor = toAnchor(otherItem)
switch config.relation {
case .greaterThanOrEqual:
return fromAnchor.constraint(greaterThanOrEqualTo: toAnchor) |> config.config
case .lessThanOrEqual:
return fromAnchor.constraint(lessThanOrEqualTo: toAnchor) |> config.config
case .equal:
return fromAnchor.constraint(equalTo: toAnchor) |> config.config
}
}
static func pin<U>(
anchor: (U) -> NSLayoutDimension,
ofItem item: U,
config: ConstraintConfig
) -> NSLayoutConstraint {
let fromAnchor = anchor(item)
switch config.relation {
case .equal:
return fromAnchor.constraint(equalToConstant: 0) |> config.config
case .greaterThanOrEqual:
return fromAnchor.constraint(greaterThanOrEqualToConstant: 0) |> config.config
case .lessThanOrEqual:
return fromAnchor.constraint(lessThanOrEqualToConstant: 0) |> config.config
}
}
}
extension UIView {
func pin<U, T>(anchor: (UIView) -> NSLayoutAnchor<T>, toAnchor: (U) -> NSLayoutAnchor<T>, ofItem: U, config: ConstraintConfig = .defaultConfig) -> NSLayoutConstraint {
return AnchorMan.pin(anchor: anchor, ofItem: self, toAnchor: toAnchor, ofOtherItem: ofItem, config: config)
}
func pin<T>(anchor: (UIView) -> NSLayoutAnchor<T>, togetherWithView: UIView, config: ConstraintConfig = .defaultConfig) -> NSLayoutConstraint {
return self.pin(anchor: anchor, toAnchor: anchor, ofItem: togetherWithView, config: config)
}
func pinToView(view: UIView, edges: [EdgeToPin] = EdgeToPin.all) -> [NSLayoutConstraint] {
return edges.map({
switch $0 {
case .top(let config):
return self.pin(anchor: Edge.top, togetherWithView: view, config: config)
case .leading(let config):
return self.pin(anchor: Edge.leading, togetherWithView: view, config: config)
case .trailing(let config):
return self.pin(anchor: Edge.trailing, togetherWithView: view, config: config)
case .bottom(let config):
return self.pin(anchor: Edge.bottom, togetherWithView: view, config: config)
}
})
}
func pinToSuperView(edges: [EdgeToPin] = EdgeToPin.all) -> [NSLayoutConstraint] {
guard let superview = self.superview else {
fatalError("Sholud have superview")
}
return self.pinToView(view: superview, edges: edges)
}
func setSize(width: ConstraintConfig? = nil, height: ConstraintConfig? = nil) -> [NSLayoutConstraint] {
return [
]
}
}
let vc = UIViewController()
let uiview = vc.view
let subview = UIView()
uiview?.addSubview(subview)
subview.pinToSuperView()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment