Slide 1

Slide 1 text

Զίϯ 2018 Summer muukii eureka, Inc. Q. Texture͸෦෼తʹಋೖͰ͖·͔͢ʁ

Slide 2

Slide 2 text

☕ ⌚ About Me • Muukii • iOS Engineer at eureka, Inc. • Pairs Global Team • GitHub : @muukii

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

1BJSTʹ͍ͭͯ !4

Slide 5

Slide 5 text

4PVUI,PSFB Japan Taiwan No.1 2017 release No.1 !5 1BJSTʹ͍ͭͯ ల։ࠃ ̐ͭͷϓϥοτϑΥʔϜ CONFIDENTIAL INFORMATION: Not for Public Distribution - Do Not Copy

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Contents • Textureʹ͍ͭͯ • TextureΛ࢖͏ཧ༝ • Textureʹগ͠৮ΕΔ • TextureΛ෦෼తʹಋೖ͢Δ • TextureΛ࢖͍ͬͯ͘ʹ͋ͨͬͯ

Slide 9

Slide 9 text

⚠ ࠓճ͸Textureͷ঺հ͕ςʔϚͰ͢ɻ ొ৔͢Δαϯϓϧίʔυ͸ਖ਼͘͠ಈ࡞͠·͕͢ɺଟগ؆ུԽ͍ͯ͠ΔͨΊέʔεʹ ΑͬͯϓϥΫςΟε͸ҟͳΔ৔߹͕͋Γ·͢ɻ

Slide 10

Slide 10 text

Textureʹ͍ͭͯ

Slide 11

Slide 11 text

• AsyncDisplayKitͱ͍͏໊લͰFacebookͰ։ൃ • PinterestʹҠಈ͠Textureʹվ໊ • PinterestͷiOSΞϓϦͰશ໘తʹ࢖༻͞Ε͍ͯΔɻ • Pinterestͷૉ੖Β͍͠ಈ͖͸TextureʹΑΔ΋ͷ Textureʹ͍ͭͯ

Slide 12

Slide 12 text

iPhone5s iPhone X

Slide 13

Slide 13 text

What is the Texture? Textureʹ͍ͭͯ • UIॲཧΛߴ଎ԽɾඇಉظԽ͢Δ͜ͱʹΑͬͯಈ͖Λ׈Β͔ʹ͢ΔϥΠϒϥϦ • ݹ͍୺຤Ͱ΋60fpsग़͢͜ͱ͕໨త • ⚠ ϨΠΞ΢τ͚ͩͷϥΠϒϥϦͰ͸ͳ͍ • UIKitΛશମతʹϥοϓͯ͠໨తΛ࣮ݱ͢ΔΞϓϩʔν • ެ։͞Εͨ࣌ͷهࣄ • https://www.infoq.com/jp/news/2014/11/facebook-asyncdisplaykit-ios

Slide 14

Slide 14 text

Before UIKit Developer Textureʹ͍ͭͯ

Slide 15

Slide 15 text

After UIKit Developer Textureʹ͍ͭͯ Texture

Slide 16

Slide 16 text

https://medium.com/@Pinterest_Engineering/re-architecting-pinterest-039-s-ios-app-e0a2d34a6ac2

Slide 17

Slide 17 text

NodeΛ௨ͯ͠UIΛૢ࡞͢Δ • ϥΠϒϥϦར༻ऀ͸UIKitΦϒδΣΫτΛૢ࡞͢ΔͷͰ͸ͳ͘ɺ
 ASDisplayNodeͱ͍͏ΦϒδΣΫτΛ௨ͯ͠UIΛૢ࡞͢Δɻ • ASDisplayNode͸όοΫάϥ΢ϯυεϨου͔Β΋ΞΫηεՄೳ • ASDisplayNode -> UIView΁ͷల։͸Texture͕ඇಉظͰߦ͏ • ల։͸MainThread͕UIૢ࡞Ͱ๩͚͠Ε͹ߋ৽ΛݟૹΔ • UIͷߋ৽Λࢭ·Βͳ͍Α͏ʹ͢ΔɾήʔϜΤϯδϯͬΆ͍ߟ͑ํ Textureʹ͍ͭͯ

Slide 18

Slide 18 text

༷ʑͳߴ଎ԽॲཧΛ࣋ͭ • ՄೳͳݶΓόοΫάϥ΢ϯυεϨουͰॲཧΛߦ͏ • UIͷϨεϙϯε଎౓͕࠷େԽ • UILabel΍UIImageView͸࢖ΘΕͣʹView or Layer ʹ Render • λοϓ൑ఆͷඞཁͷͳ͍΋ͷ͸CALayerͱͯ͠දࣔͰ͖Δ (isLayerBacked) • όοΫάϥ΢ϯυͰϝϞϦղ์Λߦ͏Ωϡʔ (releaseʹ΋ίετ͕͔͔ΔͨΊ) • ϨΠΞ΢τͷαΠζܭࢉ͸όοΫάϥ΢ϯυͰฒߦͰ࣮ߦՄೳ • CPUίΞͷଟ͍୺຤΄Ͳ༗ར Textureʹ͍ͭͯ

Slide 19

Slide 19 text

UIView

Slide 20

Slide 20 text

ASDisplayNode

Slide 21

Slide 21 text

ASDisplayNode UIView Asynchronously

Slide 22

Slide 22 text

Α͘࢖༻͢ΔΦϒδΣΫτ Core Objects

Slide 23

Slide 23 text

UIViewʹ૬౰ ASDisplayNode : NSObject http://texturegroup.org/docs/display-node.html

Slide 24

Slide 24 text

UIControlʹ૬౰ ASControlNode : ASDisplayNode http://texturegroup.org/docs/control-node.html

Slide 25

Slide 25 text

UIButtonʹ૬౰ ASButtonNode : ASControlNode http://texturegroup.org/docs/button-node.html

Slide 26

Slide 26 text

UILabelʹ૬౰ ASTextNode : ASDisplayNode http://texturegroup.org/docs/text-node.html

Slide 27

Slide 27 text

UIImageViewʹ૬౰ ը૾ͷURLΛड͚෇͚ΔASNetworkImageNode΋͋Δ ASImageNode : ASDisplayNode http://texturegroup.org/docs/image-node.html

Slide 28

Slide 28 text

UICollectionViewʹ૬౰ ASCollectionNode : ASDisplayNode http://texturegroup.org/docs/containers-ascollectionnode.html

Slide 29

Slide 29 text

UICollectionViewCellʹ૬౰ ASCollectionNodeͰ࢖༻͢ΔCell ASCellNode : ASDisplayNode http://texturegroup.org/docs/cell-node.html

Slide 30

Slide 30 text

UIKitͱTextureͷ࿈ܞ͸ൺֱత؆୯ • TextureΛ࢖͏͜ͱͰ׬શʹϩοΫΠϯ͞Εͯ͠·͏Θ͚Ͱ͸ͳ͍ • ؆୯ʹTexture͕ૢ࡞Λߦ͏UIView΁ΞΫηεՄೳ • ͦΕʹରͯ͠ΞχϝʔγϣϯΛߦ͏͜ͱ΋Մೳ • ߴ଎Խ͍ͨ͠෦෼ΛબΜͰTextureʹஔ͖׵͑Δ͜ͱ͕Մೳ Texture Overview

Slide 31

Slide 31 text

UIKitͱTextureͷ࿈ܞ͸ൺֱత؆୯ • ͲͪΒ΋Մೳ (ৄࡉ͸ࠓճ͸ׂѪ) • TextureͷίϯϙʔωϯτΛAutoLayoutϫʔϧυͰར༻͢Δ • AutoLayoutϫʔϧυͷίϯϙʔωϯτΛTextureͰར༻͢Δ Texture Overview

Slide 32

Slide 32 text

TextureΛ࢖͏ཧ༝

Slide 33

Slide 33 text

• ׈Β͔ʹಈ͘UIΛఏڙ͍͔ͨ͠Β • Ͱ͖Δ͚ͩυϩοϓϑϨʔϜΛىͨ͘͜͠ͳ͍ TextureΛ࢖͏ཧ༝

Slide 34

Slide 34 text

AutoLayout͸࣌ʹϘτϧωοΫͱͳΔ AutoLayout ManualLayout TextureΛ࢖͏ཧ༝

Slide 35

Slide 35 text

ͻͱ·ͣɺϘτϧωοΫ͕ϨΠΞ΢τͱ෼͔ͬͨͱ͖ͷରࡦ • AutoLayout ConstraintsΛνϡʔχϯά͢Δ • AutoLayoutΛ΍ΊΔ (෦෼తʹͰ΋) TextureΛ࢖͏ཧ༝

Slide 36

Slide 36 text

• ׈Β͔ʹಈ͘UIΛఏڙ͍͔ͨ͠Β • ՄೳͳݶΓυϩοϓϑϨʔϜΛى͜͞ͳ͍ • UIύϑΥʔϚϯενϡʔχϯά͸َ໳ • ϝΠϯεϨουͷ੍໿͕͋ΔͷͰ͙͢ʹݶքʹ౸ୡ͢Δ • ߴ଎ & ϚϧνεϨουରԠͷΞϓϩʔν͕Ұ൪ڧྗ • Texture! TextureΛ࢖͏ཧ༝

Slide 37

Slide 37 text

CellͷαΠζܭࢉΛ׬શʹࣗಈԽͭͭ͠ɺߴ଎ͳ·· • จࣈͷίϯςϯπ͸ΞΫηγϏϦςΟͳͲͷ؍఺ͰϢʔβʔʹΑΓจࣈαΠζ͕ม ߋͰ͖Δͷ͕๬·͍͠ UIFont.preferred~ • ࣮ݱํ๏ • AutoLayoutͰ࣮ݱ͢ΔͳΒ UIView.systemLayoutSizeFitting~ • ManualLayoutͳΒؤுΔ NSString.bounding~ • TextureͳΒ଎౓Λམͱ͢͜ͱͳ͘AutoLayoutͷΑ͏ʹαΠζܭࢉ͕Մೳ TextureΛ࢖͏ཧ༝

Slide 38

Slide 38 text

TextureΛ࢖͏͜ͱͷݒ೦ • Textureͷίϯϙʔωϯτ͸InterfaceBuilder͔Β͸࢖͑ͳ͍ • ϥΠϒϥϦ΁ͷґଘ͕ൃੜ͢Δ͜ͱ • ϥΠηϯεؔ࿈ (FacebookͷϥΠηϯε͕·ͩ࢒ͬͯΔ) • ߴ଎ԽͷͨΊʹϝϞϦ͸ଟ͘࢖༻͢Δ

Slide 39

Slide 39 text

https://github.com/muukii/TextureBook Textureʹগ͠৮ΕΔ

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

Card

Slide 43

Slide 43 text

Image Card

Slide 44

Slide 44 text

Image Card Title

Slide 45

Slide 45 text

Image Card Title Detail

Slide 46

Slide 46 text

Define Component Class

Slide 47

Slide 47 text

In UIKit Create Card View final class CardView : UIView { private let imageView: UIImageView = .init() private let titleLabel: UILabel = .init() private let detailLabel: UILabel = .init() }

Slide 48

Slide 48 text

In Texture Create Card View final class CardNode : ASDisplayNode { }

Slide 49

Slide 49 text

In Texture Create Card View final class CardNode : ASDisplayNode { private let imageNode: ASImageNode = .init() private let titleNode: ASTextNode = .init() private let detailNode: ASTextNode = .init() }

Slide 50

Slide 50 text

Define init class CardNode init(image: UIImage, title: String, detail: String) { super.init() }

Slide 51

Slide 51 text

Set initial values init(image: UIImage, title: String, detail: String) { super.init() automaticallyManagesSubnodes = true titleNode.attributedText = ... detailNode.attributedText = ... imageNode.image = ... } class CardNode

Slide 52

Slide 52 text

Define Layout

Slide 53

Slide 53 text

Define layout class CardNode override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { }

Slide 54

Slide 54 text

͜ΕΒΛ૊Έ߹ΘͤͯϨΠΞ΢τΛ࡞Γ্͛Δ ASLayoutSpec • ASWrapperLayoutSpec • ASStackLayoutSpec • ASInsetLayoutSpec • ASOverlayLayoutSpec • ASBackgroundLayoutSpec • ASCenterLayoutSpec • ASRatioLayoutSpec • ASRelativeLayoutSpec • ASAbsoluteLayoutSpec

Slide 55

Slide 55 text

let imageSpec = ASRatioLayoutSpec(ratio: 1, child: imageNode) let body = ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end, alignItems: .start, children: [ imageSpec, titleNode, detailNode ] ) return ASInsetLayoutSpec( insets: .init(top: 8, left: 8, bottom: 8, right: 8), child: body )

Slide 56

Slide 56 text

Card

Slide 57

Slide 57 text

Image 1 : 1 Card let imageSpec = ASRatioLayoutSpec( ratio: 1, child: imageNode )

Slide 58

Slide 58 text

Card Title Detail let body = ASStackLayoutSpec( direction: .vertical, spacing: 8, justifyContent: .end, alignItems: .start, children: [ imageSpec, titleNode, detailNode ] ) child: imageNode ) Image 1 : 1

Slide 59

Slide 59 text

Image Card Title Detail return ASInsetLayoutSpec( insets: .init( top: 8, left: 8, bottom: 8, right: 8 ), child: body ) detailNode ] )

Slide 60

Slide 60 text

Use Component

Slide 61

Slide 61 text

Create Node Object Use Component let node = CardNode( image: UIImage(named: "sample")!, title: "Lorem Ipsum...", detail: "Lorem Ipsum..." ) addSubview(node.view)

Slide 62

Slide 62 text

Calculate size that fits range ( Available in background thread ) node.frame.size = layout.size Use Component let layout = node.layoutThatFits( ASSizeRange( min: .init(width: 0.0, height: 250), max: .init(width: 240.0, height: .infinity) ) )

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

ߴ଎Խ͍ͨ͠ͱ͜ΖʹTextureΛ࢖͏ TextureΛ෦෼తʹಋೖ͢Δ

Slide 65

Slide 65 text

Ͳ͜ʹ࢖͏͔ TextureΛ෦෼తʹಋೖ͢Δ • ΋ͬͱ΋ޮՌతͳ෦෼͸
 ʮCellͷߴ͕͞มಈ͢ΔUITableView, UICollectionViewʯΛ࢖༻͍ͯ͠Δͱ͜Ζ

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

UIViewController UIView UIView UICollectionView Cell Cell Cell ViewTree

Slide 68

Slide 68 text

UIViewController CollectionNode CellNode ViewTree CellNode CellNode UIView UIView

Slide 69

Slide 69 text

• ݱࡏUICollectionViewΛஔ͍͍ͯΔ৔ॴΛASCollectionNodeʹஔ͖׵͑Δ TextureΛ෦෼తʹಋೖ͢Δ

Slide 70

Slide 70 text

Before UICollectionView -> ASCollectionNode class MyListViewController : UIViewController { let collectionView: UICollectionView = ... }

Slide 71

Slide 71 text

After UICollectionView -> ASCollectionNode class MyListViewController : UIViewController { let collectionNode: ASCollectionNode = ... }

Slide 72

Slide 72 text

Initialize ASCollectionNode UICollectionView -> ASCollectionNode let collectionNode: ASCollectionNode = { let layout = UICollectionViewFlowLayout() let node = ASCollectionNode(collectionViewLayout: layout) return node }()

Slide 73

Slide 73 text

Add ASCollectionView of ASCollectionNode to view UICollectionView -> ASCollectionNode override func viewDidLoad() { let collectionView = collectionNode.view view.addSubview(collectionView) // Setup AutoLayout to CollectionView }

Slide 74

Slide 74 text

DataSource, Delegate UICollectionView -> ASCollectionNode extension MyListViewController : ASCollectionDataSource, ASCollectionDelegateFlowLayout { }

Slide 75

Slide 75 text

Return number of sections UICollectionView -> ASCollectionNode func numberOfSections(in collectionNode: ASCollectionNode) -> Int { return 1 }

Slide 76

Slide 76 text

Reuse CardNode Create ASCellNode class CardNode : ASDisplayNode

Slide 77

Slide 77 text

Change superclass - ASDisplayNode -> ASCellNode Create ASCellNode class CardNode : ASCellNode class CardNode : ASDisplayNode

Slide 78

Slide 78 text

Return CellNode factory closure func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock { return { // Call on Background Thread CardNode.init(...) } } UICollectionView -> ASCollectionNode

Slide 79

Slide 79 text

Return constrained size for CellNode func collectionNode(_ collectionNode: ASCollectionNode, constrainedSizeForItemAt indexPath: IndexPath) -> ASSizeRange { return ASSizeRange( min: CGSize(width: collectionNode.bounds.width, height: 0), max: CGSize(width: collectionNode.bounds.width, height: .infinity) ) } UICollectionView -> ASCollectionNode

Slide 80

Slide 80 text

Return constrained size for CellNode func collectionNode(_ collectionNode: ASCollectionNode, constrainedSizeForItemAt indexPath: IndexPath) -> ASSizeRange { return ASSizeRange( min: CGSize(width: collectionNode.bounds.width, height: 0), max: CGSize(width: collectionNode.bounds.width, height: .infinity) ) } UICollectionView -> ASCollectionNode Width = CollectionNode.width
 Height = 0 ... infinity

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

TextureΛ࢖͏ʹ͋ͨͬͯ

Slide 83

Slide 83 text

ASViewControllerͷ࢖༻͸ඞਢͰ͸ͳ͍ • ASViewController : UIViewController ͕ఏڙ͞Ε͍ͯΔ • ը໘ͷදࣔঢ়ଶʹΑͬͯϝϞϦ؅ཧΛߦ͏ͳͲͷػೳΛఏڙ • ͨͩɺ࢖༻͸ඞਢͰ͸ͳ͍ͨΊɺطଘΞϓϦʹ͓͍ͯUIViewControllerͷܧঝઌ ͕มߋͮ͠Β͍έʔεͰ͸ແཧͯ͠࢖͏ඞཁ͸ͳ͍

Slide 84

Slide 84 text

ΞΠςϜ͕େྔʹଘࡏ͢ΔϦετ (1ສ~ Λ௒͑ΔΞΠςϜ) Texture͕޲͔ͳ͍έʔε • ΧϝϥϩʔϧͷදࣔͳͲ • શͯͷCellNode͕ੜ੒͞ΕΔͷͰϝϞϦΛѹഭ͢Δ • ASCollectionGalleryLayoutDelegateͱ͍͏΋ͷ͕͋Δ͕ɺஈ֊తʹCellNode Λ࡞Δͱ͍͏ΞϓϩʔνͰ͋Γɺ࠷ऴతͳϝϞϦ࢖༻ྔʹมΘΓ͸ͳ͍ • ͜ͷ৔߹͸UICollectionViewΛ࢖༻ͯ͠ϝϞϦ࢖༻Λ཈͑Δ޻෉Λߦ͍ͳ͕Βର ࡦͨ͠ํ͕ྑ͍

Slide 85

Slide 85 text

Texture࢖͏΂͖ͳͷʁ • Textureಋೖͷݕ౼Λߦ͏લʹ·ͣύϑΥʔϚϯεͷϘτϧωοΫΛ͔ͬ͠Γௐࠪ ͠·͠ΐ͏ɻ • ϥΠϒϥϦґଘͱֶशίετͱϋϚΓίετ͕ൃੜ͢ΔͷͰ֮ޛ͸ඞཁ • ҆ఆతʹ55fps ~ 60fps͕ཉ͍͠ͳΒࢼ͢Ձ஋͋Γ

Slide 86

Slide 86 text

Textureͷ಺෦࣮૷͸͔ͳΓษڧʹͳΔ • Texture͸ߴ଎͕ͩɺ಺෦Ͱ͸Apple͕ఏڙ͍ͯ͠Δ΋ͷΛ্खʹ࢖͍ͬͯΔ • UIKit, CoreGraphics, CoreText, CoreAnimation (C++΋) ͷѻ͍ํ͸ࢀߟʹͳΔ͜ ͱ͕ଟ͍ɻ • ಺෦࣮૷Λগ͠஌Δ͚ͩͰ΋TextureΛ࢖͑ͳ͍؀ڥͰ΋ߴ଎Խ͢ΔͨΊͷखஈ͕ ૿͑ͨ

Slide 87

Slide 87 text

ΞϓϦͷߴ଎Խͷ૬ஊ͸͍ͭͰ΋! • ʮTexture࢖͍͍ͨͱࢥͬͯΔ͚ͲɺϢʔεέʔεʹ͋ͬͯΔʁʯ • ʮTexture࢖ͬͯΔ͚Ͳɺ͜͏͍͏࣌Ͳ͏ͯ͠Δʁʯ • ʮଞͷϨΠΞ΢τΤϯδϯ͸Ͳ͏ͳΜͰ͠ΐʁʯ • ͳͲͷ͓࿩͸͍ͭͰ΋ʂ • Τ΢ϨΧͰiOS Android΋͘΋͘ձ΍ͬͯΔͷͰੋඇ༡ͼʹ͖͍ͯͩ͘͞ʂ • https://eure.connpass.com/event/100159/

Slide 88

Slide 88 text

The sample codes using Texture. https://github.com/muukii/TextureBook Thank you