Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Q. Textureは部分的に導入できますか?

Muukii
September 13, 2018

Q. Textureは部分的に導入できますか?

巷で噂となっているPinterestによって開発されている、UIが猛烈に高速化されるTexture(AsyncDisplayKit)ですが、
非常に巨大なフレームワークであり、UIKitをラップする形でAPIが提供されています。
既存のアプリで「UIが重い!Textureを入れて速くしたい!」「でも途中から導入できるものなの?」という問題に対し、
実際のところ、導入は可能なのか?どのように?についてお話しします。

Muukii

September 13, 2018
Tweet

More Decks by Muukii

Other Decks in Technology

Transcript

  1. ☕ ⌚ About Me • Muukii <Hiroshi Kimura> • iOS

    Engineer at eureka, Inc. • Pairs Global Team • GitHub : @muukii
  2. 4PVUI,PSFB Japan Taiwan No.1 2017 release No.1 !5 1BJSTʹ͍ͭͯ ల։ࠃ

    ̐ͭͷϓϥοτϑΥʔϜ CONFIDENTIAL INFORMATION: Not for Public Distribution - Do Not Copy
  3. What is the Texture? Textureʹ͍ͭͯ • UIॲཧΛߴ଎ԽɾඇಉظԽ͢Δ͜ͱʹΑͬͯಈ͖Λ׈Β͔ʹ͢ΔϥΠϒϥϦ • ݹ͍୺຤Ͱ΋60fpsग़͢͜ͱ͕໨త •

    ⚠ ϨΠΞ΢τ͚ͩͷϥΠϒϥϦͰ͸ͳ͍ • UIKitΛશମతʹϥοϓͯ͠໨తΛ࣮ݱ͢ΔΞϓϩʔν • ެ։͞Εͨ࣌ͷهࣄ • https://www.infoq.com/jp/news/2014/11/facebook-asyncdisplaykit-ios
  4. ༷ʑͳߴ଎ԽॲཧΛ࣋ͭ • ՄೳͳݶΓόοΫάϥ΢ϯυεϨουͰॲཧΛߦ͏ • UIͷϨεϙϯε଎౓͕࠷େԽ • UILabel΍UIImageView͸࢖ΘΕͣʹView or Layer ʹ

    Render • λοϓ൑ఆͷඞཁͷͳ͍΋ͷ͸CALayerͱͯ͠දࣔͰ͖Δ (isLayerBacked) • όοΫάϥ΢ϯυͰϝϞϦղ์Λߦ͏Ωϡʔ (releaseʹ΋ίετ͕͔͔ΔͨΊ) • ϨΠΞ΢τͷαΠζܭࢉ͸όοΫάϥ΢ϯυͰฒߦͰ࣮ߦՄೳ • CPUίΞͷଟ͍୺຤΄Ͳ༗ར Textureʹ͍ͭͯ
  5. In UIKit Create Card View final class CardView : UIView

    { private let imageView: UIImageView = .init() private let titleLabel: UILabel = .init() private let detailLabel: UILabel = .init() }
  6. In Texture Create Card View final class CardNode : ASDisplayNode

    { private let imageNode: ASImageNode = .init() private let titleNode: ASTextNode = .init() private let detailNode: ASTextNode = .init() }
  7. Set initial values init(image: UIImage, title: String, detail: String) {

    super.init() automaticallyManagesSubnodes = true titleNode.attributedText = ... detailNode.attributedText = ... imageNode.image = ... } class CardNode
  8. ͜ΕΒΛ૊Έ߹ΘͤͯϨΠΞ΢τΛ࡞Γ্͛Δ ASLayoutSpec • ASWrapperLayoutSpec • ASStackLayoutSpec • ASInsetLayoutSpec • ASOverlayLayoutSpec

    • ASBackgroundLayoutSpec • ASCenterLayoutSpec • ASRatioLayoutSpec • ASRelativeLayoutSpec • ASAbsoluteLayoutSpec
  9. 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 )
  10. Card Title Detail let body = ASStackLayoutSpec( direction: .vertical, spacing:

    8, justifyContent: .end, alignItems: .start, children: [ imageSpec, titleNode, detailNode ] ) child: imageNode ) Image 1 : 1
  11. Image Card Title Detail return ASInsetLayoutSpec( insets: .init( top: 8,

    left: 8, bottom: 8, right: 8 ), child: body ) detailNode ] )
  12. Create Node Object Use Component let node = CardNode( image:

    UIImage(named: "sample")!, title: "Lorem Ipsum...", detail: "Lorem Ipsum..." ) addSubview(node.view)
  13. 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) ) )
  14. Initialize ASCollectionNode UICollectionView -> ASCollectionNode let collectionNode: ASCollectionNode = {

    let layout = UICollectionViewFlowLayout() let node = ASCollectionNode(collectionViewLayout: layout) return node }()
  15. Add ASCollectionView of ASCollectionNode to view UICollectionView -> ASCollectionNode override

    func viewDidLoad() { let collectionView = collectionNode.view view.addSubview(collectionView) // Setup AutoLayout to CollectionView }
  16. Return CellNode factory closure func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath:

    IndexPath) -> ASCellNodeBlock { return { // Call on Background Thread CardNode.init(...) } } UICollectionView -> ASCollectionNode
  17. 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
  18. 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
  19. ΞΠςϜ͕େྔʹଘࡏ͢ΔϦετ (1ສ~ Λ௒͑ΔΞΠςϜ) Texture͕޲͔ͳ͍έʔε • ΧϝϥϩʔϧͷදࣔͳͲ • શͯͷCellNode͕ੜ੒͞ΕΔͷͰϝϞϦΛѹഭ͢Δ • ASCollectionGalleryLayoutDelegateͱ͍͏΋ͷ͕͋Δ͕ɺஈ֊తʹCellNode

    Λ࡞Δͱ͍͏ΞϓϩʔνͰ͋Γɺ࠷ऴతͳϝϞϦ࢖༻ྔʹมΘΓ͸ͳ͍ • ͜ͷ৔߹͸UICollectionViewΛ࢖༻ͯ͠ϝϞϦ࢖༻Λ཈͑Δ޻෉Λߦ͍ͳ͕Βର ࡦͨ͠ํ͕ྑ͍