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

レガシーなアプリケーションの 60fps化を目指す為にやっていること

レガシーなアプリケーションの 60fps化を目指す為にやっていること

iOSDC2018

8/31 17:40
@早稲田大学理工学部 西早稲田キャンパス 63号館

Avatar for satoshin21

satoshin21

August 31, 2018
Tweet

More Decks by satoshin21

Other Decks in Programming

Transcript

  1. Copyright © 2017 eureka, Inc. All rights reserved. What we’ve

    done to get High Performance in our Legacy Application ϨΨγʔͳΞϓϦέʔγϣϯͷ 60fpsԽΛ໨ࢦ͢ҝʹ΍͍ͬͯΔ͜ͱ
  2. Copyright © 2017 eureka, Inc. All rights reserved. 2 Introduce

     FVSFLB *OD  1BJSTJ04"QQMJDBUJPO&OHJOFFS  ໺ྑΧϝϥϚϯ΍ͬͯ·͢ඃࣸମʹծ͑ͯΔͷͰࣸਅࡱΒΕͯԼ͍͞ @satoshin21
  3. Copyright © 2017 eureka, Inc. All rights reserved. 3 Agenda

     1BJSTͷ঺հͱJ04νʔϜͷ՝୊  ॲཧϑϩʔΛ௥͍΍͍͢ΞʔΩςΫνϟͷಋೖ  Ϩεϙϯεͷ࠷దԽಡΈࠐΈ଎౓ߴ଎Խ  ໨ࢦͤGQT$PMMFDUJPO7JFXνϡʔχϯά  Ռͨͯ͠GQTͰվળͨ͠ͷ͔ʁ
  4. Copyright © 2017 eureka, Inc. All rights reserved. 6 ྺ࢙Λ࣋ͭPairs

     αʔϏε։࢝͸೥݄  ೥݄ʹ1BJSTGPSJ04W͕ఏڙ։࢝  ೥݄ʹϑϧεΫϥον
  5. Copyright © 2017 eureka, Inc. All rights reserved. 7 2018೥ݱࡏͷ՝୊

     0CKFDUJWF$͕ࠜװΛ୲͍ͬͯΔ෦෼͕͋Δҝɺ4XJGUͷϙςϯγϟϧΛ࠷ େݶੜ͔ͤͳ͍  ػೳ௥Ճɾվળεϐʔυ্͕͕͍ͬͯΔ͕ɺϓϩμΫτ͕ͦͷεϐʔυʹ ௥͍͚͍ͭͯͳ͍  ٕज़ෛ࠴͕ஷ·ΓɺϓϩμΫτͷύϑΥʔϚϯεʹӨڹ͕ग़࢝Ί͍ͯΔ  ͔Β࡞Γ௚͍͕ͨ͠ɺίετ͕ߴ͍
  6. Copyright © 2017 eureka, Inc. All rights reserved. 10 શମ࠷దͱ෦෼࠷ద

     શମ࠷ద΁ͷಓ͸ҰͭͰ͸ͳ͍  ෦෼తͳ࠷దԽΛߦ͍ɺͦΕΛϓϩμΫτશମʹల։͍ͯ͘͠  શମ࠷దΛݟਾ͑ͨ෦෼࠷దΛߦ͏
  7. Copyright © 2017 eureka, Inc. All rights reserved. 14 ͕͢͞ը໘ʹܾΊͨཧ༝

     ϩάΠϯޙɺҰ൪࠷ॳʹදࣔ͞ΕΔը໘  Ϣʔβʹ࠷΋ར༻͞ΕΔը໘ͷҰͭ  ϓϩμΫτ಺Ͱԣల։Մೳͳ༷ʑͳػೳ  $PMMFDUJPO7JFX Ϧϩʔυɺ௥ՃಡΈࠐΈɺ༷ʑͳσʔλΛҰཡදࣔ
  8. Copyright © 2017 eureka, Inc. All rights reserved. 15 ͕͢͞ը໘ͷ՝୊

     ൚༻Խͷҝͷଟ૚ܧঝͰॲཧ͕௥͍ʹ͍͘  Ϣʔβͷσʔλྔ͕ଟ͍ҝɺϩʔυʹ͕͔͔࣌ؒ Δ  εΫϩʔϧ࣌ʹΨλͭ͘  ฏۉdGQT J1IPOFJ04Ͱܭଌ ※ Ϣʔβը૾͸σϞ༻ʹ༻ҙͨ͠΋ͷʹͳΓ·͢
  9. Copyright © 2017 eureka, Inc. All rights reserved. 16 Τ΢ϨΧ

    ͷ iOS/Android/Web Engineer  6*69ʹ߆Γ͕ڧ͍ 6*ψϧψϧܯ࡯͕ৗற   *OTUBHSBN΍5JOEFSͳͲΠέͯΔ6*69Λ໨ࢦ͢
  10. Copyright © 2017 eureka, Inc. All rights reserved. 17 ෦෼࠷దͷ໨ඪ

     ॲཧϑϩʔΛ௥͍΍͍͢ΞʔΩςΫνϟͷಋೖ  ϢʔβͷϨεϙϯεΛ࠷దԽಡΈࠐΈͷߴ଎Խ  ໨ࢦͤGQT
  11. Copyright © 2017 eureka, Inc. All rights reserved. 19 ݱࡏͷ͕͢͞ը໘

     'BU7JFX$POUSPMMFS  ͕͢͞ը໘Ͱ͸ͭͷ7JFX$POUSPMMFSΛܧঝ͢Δଟ૚ߏ੒
  12. Copyright © 2017 eureka, Inc. All rights reserved. 20 ଟ૚ܧঝ͞ΕΔViewController

    "CTUSBDU 7JFX$POUSPMMFS ͕͢͞ը໘ 7JFX$POUSPMMFS "CTUSBDU 7JFX$POUSPMMFS "CTUSBDU 7JFX$POUSPMMFS "CTUSBDU 7JFX$POUSPMMFS "CTUSBDU 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS
  13. Copyright © 2017 eureka, Inc. All rights reserved. 21 Redux

    with ReSwift  3F4XJGU3F4XJGUΛ༻͍ͨ3FEVY-JLFͳΞʔΩςΫνϟͰ࣮ݧ  ୯Ұํ޲ͷॲཧϑϩʔ  ঢ়ଶͷදݱɾ؅ཧɾมߋͷ੹຿͕෼͚ΒΕ͍ͯΔ  ঢ়ଶΛҰͭʹू໿  ίϯϙʔωϯτΛ֦ு͠΍͍͢࡞Γ https://github.com/ReSwift/ReSwift
  14. Copyright © 2017 eureka, Inc. All rights reserved. 28 ReSwift࣮૷

     ࣮ࡍͷίʔυʹ͍ͭͯ͸࣌ؒత౎߹্ׂѪ͠·͢  ޙ΄Ͳ4QFBLFS%FDLʹσΟϨΫλʔζΧοτ൛ͱͯ͠ࢿྉΛެ։͠·͢ͷ Ͱɺ͝ࢀߟʹ͍ͯͩ͘͠͞
  15. Copyright © 2017 eureka, Inc. All rights reserved. 29 ReSwiftΛ༻͍ͨReduxͷӡ༻

     ॲཧΛ୯Ұํ޲ʹ͢Δ͜ͱʹΑͬͯɺॲཧϑϩʔΛ௥͍΍͘͢ͳͬͨ  ར༻ଆ͸ɺػೳ௥Ճ࣌ʹؾʹ͢΂͖ࣄ͕ݮͬͨ  Ҏલ͸͋ΒΏΔঢ়ଶΛ͋ΒΏΔॴͰ؅ཧ͍ͯͨ͠  "DUJPO 4UBUF 3FEVDFSͱ੹຿͕෼͚ΒΕ͍ͯΔҝɺ࣮૷ऀؒͷ࢓༷ͷζ Ϩ͕ܰݮ͞Εͨ
  16. Copyright © 2017 eureka, Inc. All rights reserved. 31 ϢʔβϨεϙϯεͷ࠷దԽ

     ͕͢͞ը໘ͰϦΫΤετͨ͠Ϣʔβ৘ใ͸͋ΒΏΔ৘ใΛؚΜͰ͍ͨ  ֤ը໘Ͱ࢖͏ҝͷϢʔβͷεςʔτͳͲ  Ϣʔβ৘ใΛੜ੒͢Δҝͷ༨ܭͳෛՙ͕αʔόαΠυʹ  NTd
  17. Copyright © 2017 eureka, Inc. All rights reserved. 32 ϢʔβϨεϙϯεͷ࠷దԽ

     ͕͢͞ը໘ͳͲɺ(SJE6*্Ͱදࣔ͢ΔϢʔβ৘ใʹඞཁ࠷௿ݶͳϨεϙϯ εΛఆٛ  ϢʔβϨεϙϯεΛ൒෼ʹ  εϐʔυվળ  NTNT
  18. Copyright © 2017 eureka, Inc. All rights reserved. 33 Ϣʔβ௥ՃಡΈࠐΈͷ࠷దԽ

     Ұ౓ʹԿ݅ϢʔβΛऔΓࠐΉ͔ɺϢʔβͷૢ࡞Λͳ Δ΂્͘֐͠ͳ͍MJNJU஋Λࢦఆ͍ͨ͠ ӈ͸मਖ਼લ   MJNJU஋Λ୹͗͢Δͱ౎౓ಡΈࠐΈ͕ൃੜ͠ɺ௕͗͢ ΔͱϨΠΞ΢τߋ৽ʹӨڹ͢Δ  ࠓͷॴ݅Λऔಘ͢Δͷ͕ྑͦ͞͏ ※ Ϣʔβը૾͸σϞ༻ʹ༻ҙͨ͠΋ͷʹͳΓ·͢
  19. Copyright © 2017 eureka, Inc. All rights reserved. 34 Ϣʔβ௥ՃಡΈࠐΈͷ࠷దԽ

     ௥ՃಡΈࠐΈͷऔಘλΠϛϯά΋มߋ  ࠓ·Ͱ͸ϖʔδ෼खલ͔ΒϦΫΤετϢʔβΛྲྀ͠ಡΈ͍ͯ͠Δ৔߹ ʹҾ͔͔ͬΓ͕͋ͬͨ  dϖʔδखલ͙Β͍͔ΒϦΫΤετ͢Δͷ͕Αͦ͞͏ʁ
  20. Copyright © 2017 eureka, Inc. All rights reserved. 35 ը૾ಡΈࠐΈߴ଎Խ

     ը૾ͷಡΈࠐΈ଎౓ͷվળ  ը૾ͷಡΈࠐΈλΠϛϯάͷݟ௚͠
  21. Copyright © 2017 eureka, Inc. All rights reserved. 36 ը૾ಡΈࠐΈߴ଎Խ

    with Nuke  LFBO/VLFͷಋೖ  Ұ௨Γͷػೳ͸׬උ  ,JOHpTIFS౳ͱൺ΂ͯ΋ߴ଎   $BDIF΍3FRVFTUपΓͷΧελϚΠζ͕͠΍͍͢ ※ https://qiita.com/H_Crane/items/422811dfc18ae919f8a4
  22. Copyright © 2017 eureka, Inc. All rights reserved. 37 ը૾ಡΈࠐΈߴ଎Խ

    with Nuke https://github.com/kean/Image-Frameworks-Benchmark
  23. Copyright © 2017 eureka, Inc. All rights reserved. 38 ը૾ಡΈࠐΈߴ଎Խ

    with Nuke https://github.com/kean/Image-Frameworks-Benchmark
  24. Copyright © 2017 eureka, Inc. All rights reserved. 39 ը૾ಡΈࠐΈߴ଎Խ

    with Nuke Nuke.loadImage( with: ImageRequest(url: url), options: ImageLoadingOptions( transition: .fadeIn(duration: 0.33) ), into: imageView) // That’s it!
  25. Copyright © 2017 eureka, Inc. All rights reserved. 40 Nuke

    with Prefetch API  J04͔Β6*$PMMFDUJPO7JFX%BUB4PVSDF1SFGFUDIJOH͕࢖͑Δ  1SFGFUDIJOH /VLF*NBHF1SFIFBUFS  XJMM%JTQMBZGPS*UFN"UͰ͍ͯͨ͠ը૾ߋ৽ΛDFMM'PS*UFN"UͰߦ͏Α͏ʹ มߋ  J04͔Βݺ͹ΕΔλΠϛϯά͕มΘͬͨ ͱͷ͜ͱ͚ͩͲ΋ɾɾʁ
  26. Copyright © 2017 eureka, Inc. All rights reserved. 41 Prefetching

    + Nuke.ImagePreheater extension UserSearchViewController: UICollectionViewDataSourcePrefetching { fileprivate let preheater: Nuke.ImagePreheater func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { DispatchQueue(label: "scene.discovery.vc.prefetch").async { [weak self] in let requests: [Nuke.ImageRequest] = indexPaths.map({..}) self?.preheater.startPreheating(with: requests) } } func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) { preheater.stopPreheating() } }
  27. Copyright © 2017 eureka, Inc. All rights reserved. 42 Prefetching

    + Nuke.ImagePreheater extension UserSearchViewController: UICollectionViewDataSourcePrefetching { fileprivate let preheater: Nuke.ImagePreheater func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { DispatchQueue(label: "scene.discovery.vc.prefetch").async { [weak self] in let requests: [Nuke.ImageRequest] = indexPaths.map({..}) self?.preheater.startPreheating(with: requests) } } func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) { preheater.stopPreheating() } }
  28. Copyright © 2017 eureka, Inc. All rights reserved. 43 Prefetching

    + Nuke.ImagePreheater extension UserSearchViewController: UICollectionViewDataSourcePrefetching { fileprivate let preheater: Nuke.ImagePreheater func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { DispatchQueue(label: "scene.discovery.vc.prefetch").async { [weak self] in let requests: [Nuke.ImageRequest] = indexPaths.map({..}) self?.preheater.startPreheating(with: requests) } } func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) { preheater.stopPreheating() } }
  29. Copyright © 2017 eureka, Inc. All rights reserved. 44 ஫ҙ఺

     1SFGFUDI"1*  දࣔ༧ఆͷ͢΂ͯͷ*OEFY1BUI͕౉͞ΕΔ༁Ͱ͸ͳ͍  DFMM'PS*UFN"U  1BJSTͷ؀ڥͰ͸΄΅XJMM%JTQMBZGPS*UFN"Uͱಉ͡λΠϛϯάͩͬͨ  Կ͔͠Βͷ޻෉͕ඞཁ͔΋
  30. Copyright © 2017 eureka, Inc. All rights reserved. 45 ϢʔβͷϨεϙϯε࠷దԽ

    & ը૾ಡΈࠐΈߴ଎Խ  ࠓ·Ͱͷഒऔಘεϐʔυ͕ૣ͍ҝɺϦϑϨογϡɺ௥ՃಡΈࠐΈ࣌ͷετ ϨεΛܰݮ  ը૾ΛεΫϩʔϧ࣌ʹ͙֬͢ೝͰ͖ΔͨΊɺϢʔβ͕͙͢ʹΞΫγϣϯͰ ͖ΔΑ͏ʹͳͬͨ
  31. Copyright © 2017 eureka, Inc. All rights reserved. 50 Fix

    AutoLayout tips  ·ͣ͸ͳ͓͢΂͖$POTUSBJOUΛ൑ผ͢Δ  /4-BZPVU$POTUSBJOUJEFOUJpFS  7JFX%FCVHHFS 3FWFBM
  32. Copyright © 2017 eureka, Inc. All rights reserved. 51 Fix

    AutoLayout tips - NSLayoutConstraint.identifier  /4-BZPVU$POTUSBJOUʹ͸JEFOUJpFS͕ઃఆՄೳ  ίʔυ্Ͱ΋ઃఆՄ
  33. Copyright © 2017 eureka, Inc. All rights reserved. 52 Fix

    AutoLayout tips - NSLayoutConstraint.identifier
  34. Copyright © 2017 eureka, Inc. All rights reserved. 54 Fix

    AutoLayout tips - Reveal  3FWFBMͰ΋ಉ༷ʹ/4-BZPVU$POTUSBJOU ΍7JFXΛΞυϨεͰݕࡧՄೳ  յΕ੍͍ͯͨ໿ΛϚʔΫͯ͘͠ΕΔҝݟ΍ ͍͢
  35. Copyright © 2017 eureka, Inc. All rights reserved. 56 Color

    Blended Layers  7JFX -BZFS ΛॏͶͯඳը͍ͯ͠Δ෦෼  ॏͳΓ߹͏ϨΠϠʔΛൺֱ͠࠷ऴతͳग़ྗ஋Λܭࢉ ͢ΔҝɺඳըύϑΥʔϚϯεʹӨڹ͢Δ
  36. Copyright © 2017 eureka, Inc. All rights reserved. 57 Color

    Blended Layers ֬ೝํ๏  4JNVMBUPSͷ৔߹  .FOV$PMPS#MFOEFE-BZFSTʹνΣοΫ
  37. Copyright © 2017 eureka, Inc. All rights reserved. 58 Color

    Blended Layers ֬ೝ  ࣮ػͷ৔߹ 9DPEF   9DPEF%FCVH7JFX%FCVHHJOH3FOEFSJOH$PMPS#MFOEFE -BZFSTʹνΣοΫ
  38. Copyright © 2017 eureka, Inc. All rights reserved. 59 Color

    Blended Layers ରࡦ - UIImageView  Ͱ͖ΔݶΓCBDLHSPVOE$PMPSΛࢦఆ͢Δ  ಁաը૾ΛͳΔ΂͘࢖Θͳ͍  ະಁաͷΑ͏ͳը૾Ͱ΋BMQIB஋ؚ͕·Ε͍ͯΔ ৔߹͕͋ΔͨΊ஫ҙ
  39. Copyright © 2017 eureka, Inc. All rights reserved. 60 Color

    Blended Layers ରࡦ - UILabel  Ͱ͖ΔݶΓCBDLHSPVOE$PMPSΛࢦఆ͢Δ  DMJQT5P#PVOETΛUSVFʹ  ೔ຊޠɾதࠃޠͳͲΛදࣔ͢Δ৔߹ɺڪΒ͘TVCMBZFS͕௥Ճ͞Ε͍ͯΔ ҝ  ˞EFTDFOU஋͕ਖ਼͘͠ઃఆ͞Ε͍ͯΔTZTUFN'POUʹݶΔ
  40. Copyright © 2017 eureka, Inc. All rights reserved. 61 Color

    Blended Layers ରࡦ - UILabel System Font + clipsToBounds HirakakuProN-W3 + clipsToBounds  MFBEJOH஋Λແࢹͯ͠DMJQ͍ͯ͠Δ https://speakerdeck.com/satoshin21/uifontdescriptor?slide=8 leading஋ͳͲʹ͍ͭͯ͸ɺҎલpotatotipsͰൃදͨ͠ࢿྉΛ͝ࢀߟʹ͍ͯͩ͘͠͞
  41. Copyright © 2017 eureka, Inc. All rights reserved. 62 Offscreen

    Rendering  ؙ֯΍ӨΛεΫϦʔϯ্ʹඳը͢ΔࡍɺϨϯμϦϯάલʹલ΋ͬͯ Φϑε ΫϦʔϯͰ ॲཧΛߦ͏  ϋʔυ΢ΣΞΞΫηϥϨʔγϣϯ (16 Λ࢖༻͍ͯ͠ͳ͍ҝύϑΥʔϚ ϯε௿ԼͷҰҼͱͳΔ  SBTUFSJ[F΋͢΂͖λΠϛϯάͱ͢΂͖Ͱͳ͍λΠϛϯά͕͋Δ  J04Ҏ߱Ͱ͸6**NBHF7JFXͰ࠷దԽ͞Ε͍ͯΔͱ͍͏͕ᷚͩɾɾ
  42. Copyright © 2017 eureka, Inc. All rights reserved. 63 Offscreen

    Rendering - ֬ೝํ๏  $PMPS#MFOEFE-BZFSTͱಉ͡ํࣜͰ 0⒎TDSFFO3FOEFSJOHΛ࣮ߦ͍ͯ͠ΔՕॴΛ৭ ෇͚Ͱ͖Δ
  43. Copyright © 2017 eureka, Inc. All rights reserved. 64 Offscreen

    Rendering - ରࡦ  ؙ֯༻ͷ.BTL7JFXΛ6**NBHF7JFXͷ্ʹ ৐ͤΔํࣜͰ0⒎TDSFFO3FOEFSJOHΛආ͚ͯ ͍Δ  վमલ͔Βߦ͍ͬͯΔҝɺৄࡉ͸ׂѪ ฐࣾͷ ϒϩάΛࢀর͍ͯͩ͘͠͞ https://medium.com/eureka-engineering/iosͷϋΠύϑΥʔϚϯεͳcorner-rounding-strategy-88a43641b554
  44. Copyright © 2017 eureka, Inc. All rights reserved. 65 ࠩ෼ߋ৽

     ݱࡏ͸௥ՃಡΈࠐΈɺ1VMMUP3FGSFTI͢Δͨͼʹ DPMMFDUJPO7JFXSFMPBE%BUB ΛݺΜͰ͍ͨ  SFMPBE%BUB ΛݺͿ͜ͱͰෆඞཁͳWJTJCMF$FMMTͷߋ৽͕࣮ߦ͞ΕΔ
  45. Copyright © 2017 eureka, Inc. All rights reserved. 66 ࠩ෼ߋ৽

    - Libraries  *OTUBHSBN*(-JTU,JU  TFDUJPOϕʔεͷࠩ෼ൺֱ  3Y4XJGU$PNNVOJUZ3Y%BUB4PVSDFT  KqJOUFS%XJ⒎U  NVVLJJ%BUB4PVSDFT
  46. Copyright © 2017 eureka, Inc. All rights reserved. 67 muukii/DataSources

     NVVLJJ%BUB4PVSDFT  *(-JTU,JUͳͲͷࠩ෼நग़ΞϧΰϦζϜΛࢀߟʹ࡞ΒΕ͍ͯΔ  λΠϓηʔϑ  ࠩ෼நग़ʹಛԽͨ͠γϯϓϧͳ࢓૊Έطଘͷ࢓૊Έͱ਌࿨ੑ͕ߴ͍  ฐࣾϝϯόʔ NVVLJJ ͕࡞͍ͬͯΔҝɺ࣭໰͕͋ͬͨΒ͙͢ฉ͚Δ
  47. Copyright © 2017 eureka, Inc. All rights reserved. 68 muukii/DataSources

    - ModelΛఆٛ enum Item { case user(User) case banner(Banner) case feature(Feature) // Ϩίϝϯυ࿮ͷΑ͏ͳ΋ͷ }
  48. Copyright © 2017 eureka, Inc. All rights reserved. 69 muukii/DataSources

    - ModelΛఆٛ import DataSources extension Item: DataSources.Diffable { typealias Identifier = String var diffIdentifier: String { switch self { case .user(let user): return user.diffIdentifier case .banner(let banner): return banner.diffIdentifier case .feature(let feature): return feature.diffIdentifier } } }
  49. Copyright © 2017 eureka, Inc. All rights reserved. 70 muukii/DataSources

    - ModelΛఆٛ import DataSources extension Item: DataSources.Diffable { typealias Identifier = String var diffIdentifier: String { switch self { case .user(let user): return user.diffIdentifier case .banner(let banner): return banner.diffIdentifier case .feature(let feature): return feature.diffIdentifier } } }
  50. Copyright © 2017 eureka, Inc. All rights reserved. 71 muukii/DataSources

    - ModelΛఆٛ import DataSources extension Item: DataSources.Diffable { typealias Identifier = String var diffIdentifier: String { switch self { case .user(let user): return user.diffIdentifier case .banner(let banner): return banner.diffIdentifier case .feature(let feature): return feature.diffIdentifier } } }
  51. Copyright © 2017 eureka, Inc. All rights reserved. 72 muukii/DataSources

    - SectionControllerΛఆٛ final class UserSearchViewController: UIViewController, StoreSubscriber { fileprivate lazy var sectionController: DataSources.SectionDataController<Item, CollectionViewAdapter> = .init( adapter: .init(collectionView: self.collectionView), displayingSection: 0, isEqual: { a, b in a.diffIdentifier == b.diffIdentifier } ) }
  52. Copyright © 2017 eureka, Inc. All rights reserved. 73 muukii/DataSources

    - SectionControllerΛఆٛ final class UserSearchViewController: UIViewController, StoreSubscriber { fileprivate lazy var sectionController: DataSources.SectionDataController<Item, CollectionViewAdapter> = .init( adapter: .init(collectionView: self.collectionView), displayingSection: 0, isEqual: { a, b in a.diffIdentifier == b.diffIdentifier } ) }
  53. Copyright © 2017 eureka, Inc. All rights reserved. 74 muukii/DataSources

    - SectionControllerΛఆٛ final class UserSearchViewController: UIViewController, StoreSubscriber { fileprivate lazy var sectionController: DataSources.SectionDataController<Item, CollectionViewAdapter> = .init( adapter: .init(collectionView: self.collectionView), displayingSection: 0, isEqual: { a, b in a.diffIdentifier == b.diffIdentifier } ) }
  54. Copyright © 2017 eureka, Inc. All rights reserved. 75 muukii/DataSources

    - SectionControllerΛఆٛ final class UserSearchViewController: UIViewController, StoreSubscriber { func newState(state: State) { switch state.loadingState { case .loaded(let items): self.sectionController.update( items: items, updateMode: .partial(animated: true), completion: { Log.info("updated") }) } } }
  55. Copyright © 2017 eureka, Inc. All rights reserved. 76 muukii/DataSources

    - SectionControllerΛఆٛ final class UserSearchViewController: UIViewController, StoreSubscriber { func newState(state: State) { switch state.loadingState { case .loaded(let items): self.sectionController.update( items: items, updateMode: .partial(animated: true), completion: { Log.info("updated") }) } } }
  56. Copyright © 2017 eureka, Inc. All rights reserved. 77 muukii/DataSources

    - SectionControllerΛఆٛ final class UserSearchViewController: UIViewController, StoreSubscriber { func newState(state: State) { switch state.loadingState { case .loaded(let items): self.sectionController.update( items: items, updateMode: .partial(animated: true), completion: { Log.info("updated") }) } } }
  57. ߋ৽લ ߋ৽ޙ 36fps 60fps 55fps iPhone 5(MD297J/A) iOS 10.3.3 ※

    Ϣʔβը૾͸σϞ༻ʹ༻ҙͨ͠΋ͷʹͳΓ·͢
  58. Copyright © 2017 eureka, Inc. All rights reserved. 82 վળ݁Ռ

     ਓؒʹ͸ཧղ͕೉͔ͬͨ͠ॲཧϑϩʔΛ3FEVYΛಋೖ͢Δ͜ͱͰΘ͔Γ΍ ͘͢ఆٛ͢Δ͜ͱ͕Ͱ͖ͨ  ৮͍ͬͯͯ৺஍͍͍6*69Λఏڙ͢Δϕʔε͕Ͱ͖ͨ  GQTΛҰͭͷࢦඪͱ͢Δ͜ͱͰɺ6*69޲্ΛఆྔԽ͢Δ͜ͱ͕Ͱ͖ͨ
  59. Copyright © 2017 eureka, Inc. All rights reserved. 83 օ͞Μʹ͓ئ͍

     Τ΢ϨΧϒʔεΛ༻ҙ͍ͯ͠·͢ʂ  ΋͠ɺύϑΥʔϚϯενϡʔχϯάʹؔͯ͠ڵຯ͕͋Δํɺʮ͜ΕΛվળ ͨ͠ΒύϑΥʔϚϯε޲্ͨ͠ΑʂʯͳͲͷϊ΢ϋ΢͕͋ΔํͳͲ͍Βͬ ͠Ό͍·ͨ͠Βɺੋඇͱ΋৘ใަ׵͠·͠ΐ͏