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.4k
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
68
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.5k
快適なUIを持つアプリを作るために できること
muukii0803
12
2.8k
iOS エンジニアが考える Webアプリ開発
muukii0803
3
530
Other Decks in Programming
See All in Programming
Lessons from Spec-Driven Development
simas
PRO
0
210
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
840
Inside Stream API
skrb
1
740
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
6.2k
Vite+ Unified Toolchain for the Web
naokihaba
0
320
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
5.3k
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
270
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
360
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
170
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
6
1.3k
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
13k
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.1k
Featured
See All Featured
Color Theory Basics | Prateek | Gurzu
gurzu
0
370
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
180
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
150
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
330
Skip the Path - Find Your Career Trail
mkilby
1
150
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
320
Designing for Timeless Needs
cassininazir
1
260
Amusing Abliteration
ianozsvald
1
210
Information Architects: The Missing Link in Design Systems
soysaucechin
0
970
How to make the Groovebox
asonas
2
2.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
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