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
70
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
530
Other Decks in Programming
See All in Programming
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
150
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
950
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
4
1.5k
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
640
テーブルをDELETEした
yuzneri
0
130
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
510
yield再入門 #phpcon
o0h
PRO
0
920
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
18k
数百円から始めるRuby電子工作
tarosay
0
130
Claude Team Plan導入・ガイド
tk3fftk
0
250
20260722_microCMSで考える、AI時代のコンテンツ運用設計
yosh1
0
290
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
1
770
Featured
See All Featured
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Between Models and Reality
mayunak
4
380
Building Adaptive Systems
keathley
44
3.2k
Side Projects
sachag
455
43k
The agentic SEO stack - context over prompts
schlessera
0
860
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
360
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
760
Claude Code のすすめ
schroneko
67
230k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
260
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
450
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
420
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