Slide 1

Slide 1 text

Farewell SnapKit さようなら、ありがとうSnapkit! pixiv Inc. kameike 亀田 彗 2018.6.5

Slide 2

Slide 2 text

- パルシィというアプリを書いているもの です - 10月に福岡から上京 2 だれ @kameike

Slide 3

Slide 3 text

宣伝

Slide 4

Slide 4 text

● SnapKitよりもAnchorがDXが良いと思うよという話 ● 最近わりと pod SnapKitを見かけたので... ● 13,000スターのスーパースター。ありがとうの気持ち、大切! 4 今日の話の要約

Slide 5

Slide 5 text

5 前提

Slide 6

Slide 6 text

6 AutoLayout(viewに制約を追加するやつ) をコードで作りたい!

Slide 7

Slide 7 text

let constraints = NSLayoutConstraint( item: subview, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1.0, constant: 0.0) 普通に作る 10

Slide 8

Slide 8 text

let constraints = NSLayoutConstraint.constraints( withVisualFormat: "H:|-15-[view]-15-|", metrics: nil, views: ["view": subView]) 例のアレ(VisualFormatLanguage) 10

Slide 9

Slide 9 text

10

Slide 10

Slide 10 text

10

Slide 11

Slide 11 text

// SnapKit subview.snp.makeConstraints { constraintMaker in constraintMaker.top.equalTo(view) constraintMaker.bottom.equalTo(view) constraintMaker.left.equalTo(view) constraintMaker.right.equalTo(view) } SnapKit 10

Slide 12

Slide 12 text

// Anchor NSLayoutConstraint.activate([ subview.topAnchor.constraint(equalTo: view.topAnchor), subview.bottomAnchor.constraint(equalTo: view.bottomAnchor), subview.trailingAnchor.constraint(equalTo: view.trailingAnchor), subview.leadingAnchor.constraint(equalTo: view.leadingAnchor) ]) Anchor(iOS9~) 10

Slide 13

Slide 13 text

13 書き方こそ似ているけども、 Anchorの方がDXが良いぞ〜! (あとUIKitだし...寿命も長いはず...)

Slide 14

Slide 14 text

14 Anchorのよさ

Slide 15

Slide 15 text

// SnapKit subview.snp.makeConstraints { constraintMaker in constraintMaker.top.equalTo(_ other: ConstraintRelatableTarget) } // ConstraintRelatableTargetとして使える型 // Int UInt Float Double CGFloat CGSize CGPoint // UIEdgeInsets, UIView SnapKit 10

Slide 16

Slide 16 text

16 暗黙的...

Slide 17

Slide 17 text

SnapKit 10

Slide 18

Slide 18 text

// Anchor subview.topAnchor.constraint(_ equalTo: NSLayoutAnchor) Anchor 10

Slide 19

Slide 19 text

Anchor 10

Slide 20

Slide 20 text

20 よさ2 ありえない組み合わせが 型によって排除されている

Slide 21

Slide 21 text

  // SnapKit subview.top.equalTo(superView.snp.right) このようなコード 10

Slide 22

Slide 22 text

期待される挙動 10

Slide 23

Slide 23 text

23 実行時エラー:sob:

Slide 24

Slide 24 text

  // Anchor view.topAnchor.constraint(equalTo: superView.leadingAnchor) Anchorだと...! 10

Slide 25

Slide 25 text

  // Anchor view.topAnchor.constraint(equalTo: superView.leadingAnchor) このようなコード 10 NSLayoutXAxisAnchor

Slide 26

Slide 26 text

26 コンパイルエラーになる:joy:

Slide 27

Slide 27 text

  // SnapKit subview.top.bottom.equalTo(view).offset(10).offset(20) ちなみにSnapKitはこんなコードを コンパイルできてしまう 10

Slide 28

Slide 28 text

28 Anchor便利...!

Slide 29

Slide 29 text

29 SnapKit->Anchorで 移行Tips

Slide 30

Slide 30 text

30 基本的にはすんなり行くはず!

Slide 31

Slide 31 text

// SnapKit let offset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) make.edges.equalTo(view).offset(offset) Edgeがほしい! 10

Slide 32

Slide 32 text

extension UIView { func edges(equalTo view: UIView, offset: UIEdgeInsets = UIEdgeInsets()) { NSLayoutConstraint.activate([ topAnchor.constraint(equalTo: view.topAnchor, constant: offset.top), bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -offset.bottom), leftAnchor.constraint(equalTo: view.leftAnchor, constant: offset.left), rightAnchor.constraint(equalTo: view.rightAnchor, constant: -offset.right) ]) } } extensionでなんとかなる!10行ぐらい! 10

Slide 33

Slide 33 text

// SnapKit view.edges.equalTo(view).offset(UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)) // Anchor+Extension view.edges(equalTo: view, offset: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)) なんとかなった...! 10

Slide 34

Slide 34 text

// leading, trailing extension UIView { func edges(equalTo view: UIView, offset: NSDirectionalEdgeInset) { NSLayoutConstraint.activate([ topAnchor.constraint(equalTo: view.topAnchor, constant: offset.top), bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -offset.bottom), leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: offset.leadingAnchor), trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -offset.trailingAnchor) ]) } } 余談 leading trailingを使いたいなら 10

Slide 35

Slide 35 text

let offset = 3 * 5 // SnapKit だと大丈夫だけど make.top.equalTo(view).offset(offset) // Anchor だとコンパイルエラー subview.topAnchor.constraint(equalTo: view.topAnchor, constant: offset) ConstraintXXXTarget的なものを CGFloatにする必要がある 10

Slide 36

Slide 36 text

36 余談の余談

Slide 37

Slide 37 text

@available(iOS 6.0, *) open func addConstraint(_ constraint: NSLayoutConstraint) // This method will be deprecated in a future release and should be avoided. // Instead, set NSLayoutConstraint's active property to YES. 10 addConstraintは 使わない方がいい

Slide 38

Slide 38 text

let constraint = view.bottomAnchor.constraint(equalTo: bottomAnchor) constraint.isActive = true // もしくは NSLayoutConstraint.activate([constraint]) // でconstraintを有効に...! こういう感じで 10

Slide 39

Slide 39 text

39 SnapKit余談

Slide 40

Slide 40 text

● 7/17にSwift4対応!(そろそろ保守されなくなってきてるって言おうとおもっていたのに) ● ので、まだ慌てる時間じゃない...!? 40 まだしっかり保守されている...!

Slide 41

Slide 41 text

● 3000行の本体コード(RxCocoaの1/3ぐらいコードがある...!) ● 大体全ての型にMapperを書いてDSL上では独自型だけで表現できる世界を実現してい る(その分よしなであり、上述の問題もあり ...) 41 整ったコード(整いすぎでは...?!)

Slide 42

Slide 42 text

42 Priorityに若干のカスタマイズ public static var medium: ConstraintPriority { #if os(OSX) return 501.0 #else return 500.0 #endif }

Slide 43

Slide 43 text

● 時々example作ったからマージしてよ!という PRがきていた ● 苦労をかんじる最適化 43 13000スターつくと何が起こるか

Slide 44

Slide 44 text

● SnapKit→Anchor ● ありがとうSnapKit!さようなら!(?) 44 まとめ