Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AutoLayout以外の選択肢
Search
Muukii
March 28, 2018
Programming
5.5k
13
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AutoLayout以外の選択肢
Muukii
March 28, 2018
More Decks by Muukii
See All by Muukii
Problem Solving from the Abstraction Layer
muukii0803
1
73
Pairs iOSとトレンドの技術
muukii0803
0
1k
Thoughts about build flow
muukii0803
2
360
スマホアプリ開発で大切なこと
muukii0803
3
190
エンジニアとして働くために
muukii0803
0
210
Q. Textureは部分的に導入できますか?
muukii0803
3
2.6k
安定したチャットを実現するための アプリとAPI設計
muukii0803
17
8.6k
快適なUIを持つアプリを作るために できること
muukii0803
12
2.8k
iOS エンジニアが考える Webアプリ開発
muukii0803
3
540
Other Decks in Programming
See All in Programming
30年振りにコンパイラの定数整数除算を改善した
herumi
9
4.3k
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
5
550
源内ハンズオン概要編
hideg
0
220
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
740
Dockerfile CMD for Node.js
grazie1999
0
140
TSX の <Hoge<Fuga>> という構文に驚いた話 / tsx-type-argument-syntax
kanaru0928
0
240
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
270
AWS Transform Customによる Spring Boot 2.xから4.xへのVerUp
satoshi256kbyte
2
110
初めての模倣学習とVLA
natsutan
0
320
ソフトウェアラスタライザ
fadis
1
720
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
440
リアルな遅延を測る仕様
kota_yata
1
130
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
It's Worth the Effort
3n
188
29k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
The Invisible Side of Design
smashingmag
301
52k
Become a Pro
speakerdeck
PRO
31
6.2k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
430
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
410
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
290
The Curse of the Amulet
leimatthew05
2
14k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
HDC tutorial
michielstock
2
820
Transcript
AutoLayoutҎ֎ͷબࢶ @muukii Akiba.swift 2018.03.28
About Me ‣ muukii <Hiroshi Kimura> ‣ iOS Engineer at
eureka, Inc. ‣ Pairs Global Team ‣ GitHub : @muukii ‣ https://muukii.me ☕ ⌚
None
Agenda › AutoLayoutͷύϑΥʔϚϯεͱସҊ › ͲΜͳ࣌ʹAutoLayoutͷύϑΥʔϚϯε͕ʹͳΔͷ͔ › ผͷϨΠΞτΤϯδϯͷհ › TextureGroup/Texture (AsyncDisplayKitʣʹ͍ͭͯհ
› ͍ํͷงғؾ (࣌ؒ͋Ε) › AutoLayoutʹର͢Δײ
ίʔυͰAutoLayoutॻ͘ͳΒ › SnapKit/SnapKit › PureLayout/PureLayout › robb/Cartography <= Couples ͱ
Pairs ຊ൛Ͱ༻த › stevestreza/Relayout › freshOS/Stevia › roberthein/TinyConstraints › nakiostudio/EasyPeasy <= ࠓͷͱ͜Ζ͓ؾʹೖΓͰւ֎൛PairsͰར༻த › Raizlabs/Anchorage › and more
AutoLayoutͷύϑΥʔϚϯε
AutoLayout੍ͷ͕૿͑Δͱ͘ͳ͍ͬͯ͘ Ҿ༻ : https://github.com/layoutBox/FlexLayout#performance AutoLayout ManualLayout
AutoLayout͕͘ͳΔ࣌ › ੍ͷ͕ଟ͍࣌ (੍ಉ࢜ͷܨ͕Γ͕ଟ͍࣌) › ༰ʹԠͯ͡େ͖͕͞มԽ͢Δίϯϙʔωϯτ͕ଟؚ͘·ΕΔ࣌ › intrinsicContentSizeΛར༻ͨ͠ϨΠΞτ › UILabelͳͲͰwidth,
heightͷ੍Λ͚ͭͳ͍࣌
͜ΜͳϨΠΞτ
͍ͱԿ͕ى͖Δʁ › UIεϨου͕ϒϩοΫ͞ΕΔ͕࣌ؒ͘ͳ͍ͬͯ͘ › ಈ͖͕͘ͳΓɺΒ͔ʹΞϓϦ(UI)͕ૢ࡞Ͱ͖ͳ͘ͳΔ › UXͷԼʹͭͳ͕͍ͬͯ͘ › ετϨε͕ཷ·Δ? ›
͕ർΕΔ?
1. AutoLayout͕ϘτϧωοΫʹͳΔέʔε › εΫϩʔϧ͢ΔUI › ϦετܥͷUI (UICollectionView/UITableView)ͷCellͷϨΠΞτʹ༻͞ Ε͍ͯΔ࣌ › ྫ
: iOSͷ௨ηϯλʔ (࠷ۙͷσόΠεͩͱΘ͔ΓͮΒ͍͔) › εΫϩʔϧ࣌ʹCellͷதͷϨΠΞτ͕͍ͱද͕ࣔΕΔ › ϑϨʔϜ͕མͪΔ › δϟϯϓ͍ͯ͠ΔΑ͏ʹݟ͑Δ › Ͱ͏ͷ͕େม
2. AutoLayout͕ϘτϧωοΫʹͳΔέʔε › ը໘ભҠͷͱ͖ › ભҠઌͷViewControllerͷϨΠΞτ͕ෳࡶͩͱॳظදࣔͷϨΠΞ τʹ͕͔͔࣌ؒΔ › ભҠΛߦ͏ϘλϯΛλοϓ͔ͯ͠ΒҰॠݻ·ΓભҠ͕ߦΘΕΔ Α͏ͳݟͨʹͳΔ
› Ԡ͕͘ײ͡ΔͷͰɺͬ͞Γͨ͠ΞϓϦʹݟ͑Δ
Ͳͷ͙Β͍ʹͳΔͷ͔? › ϨΠΞτ͚ͩͰ͋ΕͦΜͳʹʹͳΒͳ͍ › ͔͠͠ɺͦͷ΄͔ͷϩδοΫ͕ೖΔ͜ͱʹΑΓϨΠΞτͷॲཧ ͕࣌ؒϘτϧωοΫͱͳΔ
UI͕ߴʹಈ࡞͢ΔͨΊʹʁ › ը໘ͷϦϑϨογϡϨʔτ60Hz => ΠϕϯτϧʔϓͰϒϩοΫͯ͠ྑ͍࣌ؒ 16ms (1000ms / 60) ›
16msΛ͍͑ͯ͘ͱϑϨʔϜ͕ͲΜͲΜམ͍ͪͯ͘(υϩοϓϑϨʔϜ) › ͜ͷؒʹUIKitࣗମͷॲཧೖΔͷͰࢲ͕ͨͪॻ͘ίʔυ10ms͙Β͍ʹ͍ͨ͠ ͷ › ࠷ۙͷiPad Pro120HzʹͳͬͯΔͷͰɺͬͱ͘͠ͳ͍ͱσΟεϓϨΠͷՁ ൃش͞Εͳ͍ɻૢ࡞ʹΑΔεΫϩʔϧͷ͞ʹCellͷද͕͍͔ࣔͭͳ͚Εͳ Βͳ͍ɻ ͦͦ
UI͕ߴʹಈ࡞͢ΔͨΊʹʁ › ͔͠͠ɺͲΜͳʹࣗͨͪͷίʔυΛ࠷దԽͯͦ͠ͷݶք͋Δ › AutoLayoutͷίετΛݮΒ͢ͷ͍͠ ϨΠΞτॲཧ ϨΠΞτॲཧ ͦͷଞϩδοΫ ͦͷଞϩδοΫ 16ms
࠷దԽ 0ms
ϨΠΞτҎ֎ͷϩδοΫͦΜͳʹߴԽͰ͖ͳ͍ › Α΄Ͳॏ͍ॲཧΛॻ͍͍ͯͳ͍ݶΓɺ͢Ͱʹߴͳίʔυʹͳͬͯ ͍ΔՄೳੑߴ͍ › ϨΠΞτॲཧΛͲ͏ʹ͔͠ͳ͍ݶΓυϩοϓϑϨʔϜආ͚Β Εͳ͍ ࣮ࡍͷͱ͜Ζ
ϨΠΞτॲཧ͕ߴʹͳΕɺͦͷଞͷ ϩδοΫʹCPUϦιʔεΛඅ͢͜ͱ͕Ͱ ͖ΔΑ͏ʹͳΔ ϨΠΞτॲཧ ͦͷଞϩδοΫ 16ms ͜͏͍ͨ͠ 0ms ͦͷଞϩδοΫ
AutoLayoutΛΊͯΈΔ
ͱ͍͑ɺView.frame৮Γͨ ͘ͳ͍
ผͷϨΠΞτΤϯδϯ › facebook/Yoga (ւ֎൛PairsͰ༻த) › TextureGroup/Texture (ւ֎൛PairsͰ༻த) › mirego/PinLayout (ͪΐͬͱ৮ͬͯߟ͑த)
› linkedin/LayoutKit › mirego/PinLayout › mamaral/Neon
facebook/yoga *
Yoga › FacebookʹΑͬͯ։ൃ͞Ε͍ͯΔ › ඇৗʹߴͳΫϩεϓϥοτϑΥʔϜͳϨΠΞτΤϯδϯ › AutoLayoutͱൺֱͯ͠8ഒఔ͍ › https://github.com/layoutBox/FlexLayout#performance
Yoga › CSS Flexbox Layoutͱඇৗʹ͍ۙಈ࡞ͱࢦఆํࣜ › جຊUIStackViewͷverticalͱhorizontalΛΈ߹ΘͤͯϨΠΞ τ͢Δײ֮ › ίΞͱͳΔίʔυC++Ͱ3000ߦ΄Ͳ
› ؤுΕಡΊͦ͏Ͱ͢ɻ
Yoga › UIView.sizeThatFitsΛݺͼग़ͯ͠༰ʹԠͨ͡αΠζΛܾఆ͢Δ › ReactNativeͰΘΕ͍ͯΔ › ͜Εͭ·ΓɺReactNativeΞϓϦͷํ͕UIͷಈ࡞͕͍Մೳੑ ͕͋Δͱ͍͏͜ͱ
Yoga › APIͱͯ͠Objective-C༻ͳͷͰSwift͔Βͪΐͬͱ͍ͮΒ͍ › layoutBox/FlexLayoutͱ͍͏Swift༻ʹYogaΛϥοϓͨ͠ͷ͕͋ Δ › muukii/Mondrian͍ͬͯ͏ͷ࡞ͬͯΈͯΔ(ࠓࢭ·ͬͯΔ)
TextureGroup/Texture
Texture › ݩͷ໊AsyncDisplayKit › PinterestͷiOSΞϓϦͰશ໘తʹ༻͞Ε͍ͯΔɻ › PinterestͷૉΒ͍͠ಈ͖Textureͷύϫʔ
Texture › UIKitΛϥοϓ͢ΔܗͰUIύϑΥʔϚϯεΛ࠷େ·ͰҾ্͖͛ΔϥΠ ϒϥϦ › Objective-C++ʹΑΔ࣮
Texture › ϥΠϒϥϦར༻ऀUIKitΦϒδΣΫτΛૢ࡞͢ΔͷͰͳ͘ɺNodeͱ͍͏ΦϒδΣΫ τΛ௨ͯ͠UIΛૢ࡞͢Δɻ › NodeεϨουηʔϑͰ͋ΓɺόοΫάϥϯυεϨου͔ΒมߋՄೳ › Node -> UIViewͷల։Texture͕ߦ͏
› ඇಉظͰUIΛߋ৽͢Δ (AsyncʹDisplay͢Δ) › MainThread͕UIૢ࡞Ͱ͚͠Εߋ৽ΛݟૹΔ › UI͕ݻ·Βͳ͍ › ήʔϜΤϯδϯͬΆ͍ߟ͑ํ
Nodeͷछྨ › ASDisplayNode : NSObject › ASTextNode : ASDisplayNode -
UILabelͷΘΓ › ASImageNode : ASDisplayNode - UIImageViewͷΘΓ › ASButtonNode : ASDisplayNode - UIButtonͷΘΓ › ASCellNode : ASDisplayNode - UICollectionViewCell/UITableViewCellͷ ΘΓ › and more… Texture
ϨΠΞτ › ϨΠΞτNodeʹίʔυͰهड़ › CSS FlexboxͷۭؾײΛҾ͖ܧ͍Ͱ͓Γɺ͞ΒʹUIϨΠΞτʮ͋ Δ͋ΔʯʹରԠ͍͢͠هड़ํ๏͕༻ҙ͞Ε͍ͯΔɻ › ׳Εͯ͘ΔͱUIͷ։ൃͷޮ͕Α͘ͳΔ ›
ܭࢉYogaฒΈʹ͍͔ͱࢥΘΕΔ Texture
ڻ͘΄Ͳͷ࠷దԽ › ՄೳͳݶΓόοΫάϥϯυεϨουͰॲཧΛߦ͏ › UIͷϨεϙϯε͕࠷େԽ › UILabelUIImageViewΘΕͣʹϨΠϠʔʹϨϯμϦϯά › λοϓఆͷඞཁͷͳ͍ͷCALayerͱͯ͠දࣔ (layerBacking)
(UIViewΑΓϝϞϦফඅ͕͑ΒΕΔͨΊ) › όοΫάϥϯυͰϝϞϦղ์Λߦ͏Ωϡʔ (releaseʹCPUίετ͕͔͔ΔͨΊ) › Nodeʹهड़ͨ͠ϨΠΞτόοΫάϥϯυͰαΠζܭࢉ͕Մೳ › ConcurrentͰ࣮ߦ͞ΕΔͨΊɺNode͕࣋ͭσʔλ͕ଞεϨουʹґଘ͍ͯ͠ͳ͚ΕɺCPUͷίΞ͕ϑ ϧͰ͑Δ › iPhoneXͳΒ6ݸCellಉ࣌ʹܭࢉ Texture
TextureΛ࣮ͬͨͷงғؾ https://github.com/muukii/PlayTexture ࡉ͔͘આ໌͢Δͱ͕͘ͳͬͯ͠·͏ͷͰงғؾ͚ͩʹ͓͖ͯ͠·͢ɻ
None
None
UIKit class CardView : UIView { } ௨ৗ௨ΓUIKitͰViewΛ࡞ΔͳΒUIViewͷαϒ ΫϥεΛ࡞ͯ͠ViewΛ͍͖ͭͬͯ͘·͢
Texture // Textureʹͳ͚ͬͨͲModuleͷ໊લݹ͍·· import AsyncDisplayKit class CardNode : ASDisplayNode {
} TextureͰUIViewͷΘΓʹ ASDisplayNodeͷαϒΫϥεΛ࡞͠·͢ɻ
import AsyncDisplayKit class CardNode : ASDisplayNode { private let imageNode:
ASImageNode = .init() private let titleNode: ASTextNode = .init() private let detailNode: ASTextNode = .init() } ίϯϙʔωϯτΛఆٛ
class CardNode : ASDisplayNode { … init(image: UIImage, title: String,
detail: String) { super.init() titleNode.attributedText = NSAttributedString( string: title, attributes: […] ) detailNode.attributedText = NSAttributedString( string: detail, attributes: […] ) imageNode.image = image addSubnode(imageNode) addSubnode(titleNode) addSubnode(detailNode) // addSubnodeͷΘΓʹ `automaticallyManagesSubnodes = true` ͰΑ͍ } }
class CardNode : ASDisplayNode { … override func layoutSpecThatFits(_ constrainedSize:
ASSizeRange) -> ASLayoutSpec { // ⭐ ͜͜ʹϨΠΞτΛهड़͢Δ } }
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { return ASRatioLayoutSpec(
ratio: 1.6, child: ASBackgroundLayoutSpec( child: ASInsetLayoutSpec( insets: .init(top: 8, left: 8, bottom: 8, right: 8), child: ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end, alignItems: .start, children: [ titleNode, detailNode, ] ) ), background: imageNode ) ) }
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { return ASRatioLayoutSpec(
ratio: 1.6, child: ASBackgroundLayoutSpec( child: ASInsetLayoutSpec( insets: .init(top: 8, left: 8, bottom: 8, right: 8), child: ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end, alignItems: .start, children: [ titleNode, detailNode, ] ) ), background: imageNode ) ) }
let info = ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end,
alignItems: .start, children: [ titleNode, detailNode, ] ) Vertical
let body = ASBackgroundLayoutSpec( child: info, background: imageNode ) let
info = ASStackLayoutSpec(…
class CardNode : ASDisplayNode { … override func layoutSpecThatFits(_ constrainedSize:
ASSizeRange) -> ASLayoutSpec { return ASRatioLayoutSpec( ratio: 1.6, // ॎͷΧʔυͰදࣔ͢ΔͨΊbodyͷΞεϖΫτൺΛࢦఆ͢Δ child: body ) } }
let node = CardNode( image: UIImage(named: "sample")!, title: "Lorem Ipsum",
detail: "Lorem Ipsum……" ) view.addSubnode(node) let layout = node.calculateLayoutThatFits( ASSizeRange( min: .init(width: 0.0, height: 0), max: .init(width: 240.0, height: .infinity) ) ) node.frame.size = layout.size In ViewController ࣮ࡍɺ͜͏͍͏ίʔυ͋·Γॻ͔ͳ͍Ͱ͢ɻ CardNodeΛॳظԽ ViewController.viewʹaddSubnode nodeͷαΠζܭࢉΛߦ͏ αΠζͷRangeΛ༩͑Δ UIView.sizeThatFitsͷײ֮
None
let insetInfo = ASInsetLayoutSpec( insets: UIEdgeInsets( top: 8, left: 8,
bottom: 8, right: 8 ), child: info ) let info = ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end, alignItems: .start, children: [ titleNode, detailNode, ] )
let body = ASBackgroundLayoutSpec( child: info, background: imageNode ) let
body = ASBackgroundLayoutSpec( child: insetInfo, background: imageNode )
None
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { return ASRatioLayoutSpec(
ratio: 1.6, child: ASBackgroundLayoutSpec( child: ASInsetLayoutSpec( insets: .init(top: 8, left: 8, bottom: 8, right: 8), child: ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end, alignItems: .start, children: [ titleNode, detailNode, ] ) ), background: imageNode ) ) } શ෦·ͱΊΔͱ
DispatchQueue.global().async { let layout = node.calculateLayoutThatFits( ASSizeRange( min: .init(width: 0.0,
height: 0), max: .init(width: 240.0, height: .infinity) ) ) DispatchQueue.main.async { node.frame.size = layout.size } } όοΫάϥϯυͰαΠζܭࢉ
·ͱΊ › AutoLayoutॊೈͰڧྗͳϨΠΞτΤϯδϯ͕ͩɺ·ͩύϑΥʔϚϯε໘Ͱ՝ ͕͋Δɻ › ҰԠɺ࠷ۙͷiOSͰϨΠΞτॲཧΛগͳͤ͘͞Δೖ͖͍ͬͯͯΔ › UICollectionViewͷestimated~ͱ͔ › ݱঢ়ɺCPUͷΫϩοΫͷ৳ͼʹظͮ͠Β͍ͷͰɺUIύϑΥʔϚϯε্ͷ
ͨΊʹϚϧνεϨουʹΑΔΞϓϩʔν͕ඞਢʹͳͬͯ͘Δͣɻ › ͔͠͠ɺUIKitݱ࣌ͰϚϧνεϨουʹରԠ͍ͯ͠ͳ͍ɻ
·ͱΊ › ͜ͷݱঢ়ʹରͯ͠ɺFacebook,Instagram,PinterestͷΑ͏ͳαʔϏεϓϩμΫτʹ͓ ͍ͯAutoLayoutͷ༻Λආ͚͓ͯΓɺͦΕͧΕ͕UIύϑΥʔϚϯεΛ࠷େԽ͢ΔOSS Λެ։͍ͯ͠Δ › Pinterest - Texture ›
Facebook - ComponentKit, ReactNative, Texture › Instagram - IGListKit (ͪΐͬͱझࢫҧ͏͚Ͳ) › ͜ͷঢ়گʹରͯ͠ɺࠓޙApple͕औΔUIKitͷߟָ͕͑͠ΈͰ͢ɻAutoLayoutؤுͬ ͯཉ͍͠Ͱ͢Ͷʂ
Thank you