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

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

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for matuyuji matuyuji
April 11, 2015

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

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

Avatar for matuyuji

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Λ࢖ͬͯ·͢ɻ