Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Visual Format Languageが 簡単に書けるSwiftライブラリ yavfl

matuyuji
April 11, 2015

Visual Format Languageが 簡単に書けるSwiftライブラリ yavfl

iOS, OS XでAuto LayoutのVisual Format Languageを簡潔に書けるようにするためのライブラリyavfl (https://github.com/safx/yavfl) の実装を簡単に紹介します。

matuyuji

April 11, 2015
Tweet

More Decks by matuyuji

Other Decks in Technology

Transcript

  1. 2ͭͷViewΛಉ͡෯Ͱԣʹฒ΂Δ Visual Format Language let dic = ["l": label, "t":

    textField] label.setTranslatesAutoresizingMaskIntoConstraints(false) textField.setTranslatesAutoresizingMaskIntoConstraints(false) let c1 = NSLayoutConstraint.constraintsWithVisualFormat(“V:|-40-[l(32)]", options: nil, metrics: nil, views: dic) let c2 = NSLayoutConstraint.constraintsWithVisualFormat(“V:|-40-[t(32)]", options: nil, metrics: nil, views: dic) let c3 = NSLayoutConstraint.constraintsWithVisualFormat(“|-20-[l(==t)]-10-[t]-|", options: nil, metrics: nil, views: dic) self.view.addConstraints(c1) self.view.addConstraints(c2) self.view.addConstraints(c3)
  2. yavfl: Yet Another VFL visualFormat(label, textField) { l, t in

    .V ~ |-40-[l,==32] .V ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } ΍ Ϳ ; Δ
  3. Visual Format Language yavfl visualFormat(label, textField) { l, t in

    .V ~ |-40-[l,==32] .V ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } let dic = ["l": label, "t": textField] label.setTranslatesAutoresizingMaskIntoConstraints(false) textField.setTranslatesAutoresizingMaskIntoConstraints(false) let c1 = NSLayoutConstraint.constraintsWithVisualFormat(“V:|-40-[l(32)]", options: nil, metrics: nil, views: dic) let c2 = NSLayoutConstraint.constraintsWithVisualFormat(“V:|-40-[t(32)]", options: nil, metrics: nil, views: dic) let c3 = NSLayoutConstraint.constraintsWithVisualFormat(“|-20-[l(==t)]-10-[t]-|", options: nil, metrics: nil, views: dic) self.view.addConstraints(c1) self.view.addConstraints(c2) self.view.addConstraints(c3)
  4. ಛ௃ • Visual Format Language෩ͷݴޠ • (VFLͷ) Predicate΍PriorityͳͲʹ΋ҰԠରԠ • ίϯύΠϧ࣌ʹνΣοΫ͞ΕΔͷͰ҆৺

    • XcodeͰͷิ׬ • Mac, iOS྆ରԠ • CocoaPodsͰ؆୯ಋೖ • Swift 1.2ඇରԠ
  5. yavflͷॲཧ (֓ཁ) • SwiftͷݴޠػೳΛ͍Ζ͍Ζ࢖ͬͯɺ • Visual Format LanguageͷจࣈྻΛ࡞ͬͯɺ • NSLayoutConstraintͷ

    constraintsWithVisualFormat:options:metrics:views Λద༻͢Δ͚ͩ ςετ͕ɺZBWqͷදهˠ7'-ͷදهͷ ม׵͕ਖ਼͍͜͠ͱͷνΣοΫ͚ͩͰࡁΉ
  6. Trailing Closures visualFormat(label, textField) { l, t in .V ~

    |-40-[l,==32] .V ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } func visualFormat(v1: UIView, v2: UIView, closure:(ViewExpression, ViewExpression) -> ())
  7. visualFormat func visualFormat(v1: YAVView, v2: YAVView, closure: (ViewExpression, ViewExpression) ->

    ()) { v1.yav_setTranslatesAutoresizingMaskIntoConstraints(false) v2.yav_setTranslatesAutoresizingMaskIntoConstraints(false) closure(.View(LayoutViewName(v1, 1)), .View(LayoutViewName(v2, 2))) v1.updateConstraints() v2.updateConstraints() }
  8. visualFormat(label, textField) { l, t in .V ~ |-40-[l,==32] .V

    ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } { l, t in .V ~ |-40-[l,==32] .V ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| }
  9. visualFormat(label, textField) { l, t in .V ~ |-40-[l,==32] .V

    ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } .H ~ |-20-[l,==t]-10-[t]-| enum
  10. Visual Format String Grammarʹج͍ͮͨ஋Λఆٛ enum VisualFormat { case Superview case

    View(LayoutView) case Connection case Predicate(LayoutPredicate) case Number(Int) case Composition([VisualFormat]) case Options(NSLayoutFormatOptions) } | [l] - 20 ==t
  11. IntegerLiteralConvertible enum VisualFormat : IntegerLiteralConvertible { case Superview case View(LayoutView)

    case Connection case Predicate(LayoutPredicate) case Number(Int) case Composition([VisualFormat]) case Options(NSLayoutFormatOptions) } let vf: VisualFormat = 3 IntegerLiteralConvertible case Number(Int) public init(integerLiteral value: IntegerLiteralType) { self = .Number(value) } }
  12. enum VisualFormat : IntegerLiteralConvertible, ArrayLiteralConvertible { case Superview case View(LayoutView)

    case Connection case Predicate(LayoutPredicate) case Number(Int) case Composition([VisualFormat]) case Options(NSLayoutFormatOptions) public init(integerLiteral value: IntegerLiteralType) { self = .Number(value) } public init(arrayLiteral elements: ViewExpression...) { self = .View(LayoutView(elements)) } } nshipster.com/swift-literal-convertible Swift Literal Convertibles let w1: ViewExpression = .View(LayoutViewName(v1, 1)) let w2: ViewExpression = .View(LayoutViewName(v2, 2)) let vf: VisualFormat = [w1,==w2]
  13. visualFormat(label, textField) { l, t in .V ~ |-40-[l,==32] .V

    ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } .H ~ |-20-[l,==t]-10-[t]-| (ArrayLiteralConvertible) VisualFormat (IntegerLiteralConvertible) VisualFormat LayoutOrientation
  14. Custom Operators • લஔ (prefix), ޙஔ (postfix), தஔ (infix) •

    ༏ઌॱҐ (precedence) • ݁߹ੑ (associativity) a + b * c a ~ (b ~ c) (a ~ b) ~ c a ~ b ~ c ++a a++ a + b a + (b * c) (a + b) * c
  15. visualFormat(label, textField) { l, t in .V ~ |-40-[l,==32] .V

    ~ |-40-[t,==32] .H ~ |-20-[l,==t]-10-[t]-| } .H ~ |-20-[l,==t]-10-[t]-| prefix postfix infix
  16. prefix operator |- {} public prefix func |- (e: VisualFormat)

    -> VisualFormat { return VisualFormat(composition: .Superview, .Connection, e) } .H ~ |-20-[l,==t]-10-[t]-| .Number(20)
  17. .H ~ |-20-[l,==t]-10-[t]-| .H ~ |- - - - -|

    20 l 10 t - | 20 - t | l 10 .H ~ - - - - | 20 - t | l 10 .H ~ - - - public func -(lhs: VisualFormat, rhs: VisualFormat) -> VisualFormat { return VisualFormat(composition: lhs, .Connection, rhs) }
  18. .H ~ |-20-[l,==t]-10-[t]-| public func ~(lhs: LayoutOrientation, rhs: VisualFormat) ->

    [AnyObject] { if let superView = rhs.superView? { let exp = lhs.description + ":" + rhs.description let dic = rhs.viewsDictionary let opts = rhs.options let c = NSLayoutConstraint.constraintsWithVisualFormat(exp, options: opts, metrics: nil, views: dic) superView.addConstraints(c) return c } return [] } - | 20 - t | l 10 .H ~ - - - H:|-20-[l(==t)]-10-[t]-| ==t
  19. Grammar of Operators (from Language Reference) operator → operator-head operator-characters

    opt operator → dot-operator-head dot-operator-characters opt operator-head → / | = | - | + | ! | * | % | < | > | & | | | ^ | ~ | ? operator-head → U+00A1–U+00A7 operator-head → U+00A9 or U+00AB operator-head → U+00AC or U+00AE operator-head → U+00B0–U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7 operator-head → U+2016–U+2017 or U+2020–U+2027 ɿ # $ @ : , ͳͲ͸࢖͑ͳ͍
  20. mattt/Euler Swift Custom Operators for Mathematical Notation infix operator ∈

    { associativity left } func ∈ <T: Equatable> (left: T, right: [T]) -> Bool { return contains(right, left) } print(2 ∈ [2,3,4]) // true print(1 ∈ [2,3,4]) // false
  21. Build Configurations OSͷҧ͍Λٵऩ #if os(iOS) import UIKit public typealias YAVView

    = UIView #else import AppKit public typealias YAVView = NSView #endif extension YAVView { private func yav_setTranslatesAutoresizingMaskIntoConstraints(flag: Bool) { #if os(iOS) setTranslatesAutoresizingMaskIntoConstraints(flag) #else translatesAutoresizingMaskIntoConstraints = flag #endif } }
  22. ·ͱΊ • Auto LayoutϥΠϒϥϦyavflͰ͸ɺ • Trailing ClosureͷதͰɺ • ArrayLiteralConvertibleͳͲͰద౰ͳenum஋ʹม͑ͭͭɺ •

    Custom OperatorͰͦΕΒΛ഑ྻʹ·ͱΊ͔ͯΒɺ • ͦΕΛจࣈྻʹม׵ͯ͠NSLayoutConstraint. constraintsWithVisualFormatΛ࢖ͬͯ·͢ɻ