iOSDC2018
8/31 17:40 @早稲田大学理工学部 西早稲田キャンパス 63号館
Copyright © 2017 eureka, Inc. All rights reserved.What we’ve done to get High Performance in our Legacy ApplicationϨΨγʔͳΞϓϦέʔγϣϯͷ60fpsԽΛࢦ͢ҝʹ͍ͬͯΔ͜ͱ
View Slide
Copyright © 2017 eureka, Inc. All rights reserved.2Introduce FVSFLB *OD 1BJSTJ04"QQMJDBUJPO&OHJOFFS ྑΧϝϥϚϯͬͯ·͢ඃࣸମʹծ͑ͯΔͷͰࣸਅࡱΒΕͯԼ͍͞@satoshin21
Copyright © 2017 eureka, Inc. All rights reserved.3Agenda 1BJSTͷհͱJ04νʔϜͷ՝ ॲཧϑϩʔΛ͍͍͢ΞʔΩςΫνϟͷಋೖ Ϩεϙϯεͷ࠷దԽಡΈࠐΈߴԽ ࢦͤGQT$PMMFDUJPO7JFXνϡʔχϯά Ռͨͯ͠GQTͰվળͨ͠ͷ͔ʁ
Copyright © 2017 eureka, Inc. All rights reserved.Pairsͷհ & iOSνʔϜͷ՝
Copyright © 2017 eureka, Inc. All rights reserved.6ྺ࢙Λ࣋ͭPairs αʔϏε։݄࢝ ݄ʹ1BJSTGPSJ04W͕ఏڙ։࢝ ݄ʹϑϧεΫϥον
Copyright © 2017 eureka, Inc. All rights reserved.72018ݱࡏͷ՝ 0CKFDUJWF$͕ࠜװΛ୲͍ͬͯΔ෦͕͋Δҝɺ4XJGUͷϙςϯγϟϧΛ࠷େݶੜ͔ͤͳ͍ ػೳՃɾվળεϐʔυ্͕͕͍ͬͯΔ͕ɺϓϩμΫτ͕ͦͷεϐʔυʹ͍͚͍ͭͯͳ͍ ٕज़ෛ࠴͕ஷ·ΓɺϓϩμΫτͷύϑΥʔϚϯεʹӨڹ͕ग़࢝Ί͍ͯΔ ͔Β࡞Γ͍͕ͨ͠ɺίετ͕ߴ͍
Ͳ͏ʹ͔վળ͍ͨ͠
͍͖ͳΓશͯΛ࡞Γม͑ΔͷͰͳ͘શମ࠷దԽʹ͚ͯҰาͮͭਐΉ
Copyright © 2017 eureka, Inc. All rights reserved.10શମ࠷దͱ෦࠷ద શମ࠷దͷಓҰͭͰͳ͍ ෦తͳ࠷దԽΛߦ͍ɺͦΕΛϓϩμΫτશମʹల։͍ͯ͘͠ શମ࠷దΛݟਾ͑ͨ෦࠷దΛߦ͏
෦࠷దΛ͢ΔͷͰ͋Εɾɾ
Ϣʔβ͕ޮՌΛ࣮ײ͍͢͠& ཏతͳػೳ͕ଘࡏ͢Δ
ϢʔβΛ͕͢͞ը໘
Copyright © 2017 eureka, Inc. All rights reserved.14͕͢͞ը໘ʹܾΊͨཧ༝ ϩάΠϯޙɺҰ൪࠷ॳʹදࣔ͞ΕΔը໘ Ϣʔβʹ࠷ར༻͞ΕΔը໘ͷҰͭ ϓϩμΫτͰԣల։Մೳͳ༷ʑͳػೳ $PMMFDUJPO7JFX ϦϩʔυɺՃಡΈࠐΈɺ༷ʑͳσʔλΛҰཡදࣔ
Copyright © 2017 eureka, Inc. All rights reserved.15͕͢͞ը໘ͷ՝ ൚༻ԽͷҝͷଟܧঝͰॲཧ͕͍ʹ͍͘ Ϣʔβͷσʔλྔ͕ଟ͍ҝɺϩʔυʹ͕͔͔࣌ؒΔ εΫϩʔϧ࣌ʹΨλͭ͘ ฏۉdGQT J1IPOFJ04Ͱܭଌ※ Ϣʔβը૾σϞ༻ʹ༻ҙͨ͠ͷʹͳΓ·͢
Copyright © 2017 eureka, Inc. All rights reserved.16ΤϨΧ ͷ iOS/Android/Web Engineer 6*69ʹ߆Γ͕ڧ͍ 6*ψϧψϧܯ͕ৗற *OTUBHSBN5JOEFSͳͲΠέͯΔ6*69Λࢦ͢
Copyright © 2017 eureka, Inc. All rights reserved.17෦࠷దͷඪ ॲཧϑϩʔΛ͍͍͢ΞʔΩςΫνϟͷಋೖ ϢʔβͷϨεϙϯεΛ࠷దԽಡΈࠐΈͷߴԽ ࢦͤGQT
Copyright © 2017 eureka, Inc. All rights reserved.ॲཧϑϩʔΛ͍͍͢ΞʔΩςΫνϟͷಋೖ
Copyright © 2017 eureka, Inc. All rights reserved.19ݱࡏͷ͕͢͞ը໘ 'BU7JFX$POUSPMMFS ͕͢͞ը໘Ͱͭͷ7JFX$POUSPMMFSΛܧঝ͢Δଟߏ
Copyright © 2017 eureka, Inc. All rights reserved.20ଟܧঝ͞ΕΔViewController"CTUSBDU7JFX$POUSPMMFS͕͢͞ը໘7JFX$POUSPMMFS"CTUSBDU7JFX$POUSPMMFS"CTUSBDU7JFX$POUSPMMFS"CTUSBDU7JFX$POUSPMMFS"CTUSBDU7JFX$POUSPMMFS6*7JFX$POUSPMMFS
Copyright © 2017 eureka, Inc. All rights reserved.21Redux with ReSwift 3F4XJGU3F4XJGUΛ༻͍ͨ3FEVY-JLFͳΞʔΩςΫνϟͰ࣮ݧ ୯Ұํͷॲཧϑϩʔ ঢ়ଶͷදݱɾཧɾมߋͷ͕͚ΒΕ͍ͯΔ ঢ়ଶΛҰͭʹू ίϯϙʔωϯτΛ֦ு͍͢͠࡞Γhttps://github.com/ReSwift/ReSwift
https://github.com/ReSwift/ReSwift
6TFS4FBSDI"DUJPO6TFS4FBSDI7JFX$POUSPMMFS"QQ4UPSF"QQ4UBUF6TFS4FBSDI4UBUF"QQ3FEVDFS 6TFS4FBSDI3FEVDFS.JEEMFXBSF
Copyright © 2017 eureka, Inc. All rights reserved.28ReSwift࣮ ࣮ࡍͷίʔυʹ͍ͭͯ࣌ؒత߹্ׂѪ͠·͢ ޙ΄Ͳ4QFBLFS%FDLʹσΟϨΫλʔζΧοτ൛ͱͯ͠ࢿྉΛެ։͠·͢ͷͰɺ͝ࢀߟʹ͍ͯͩ͘͠͞
Copyright © 2017 eureka, Inc. All rights reserved.29ReSwiftΛ༻͍ͨReduxͷӡ༻ ॲཧΛ୯Ұํʹ͢Δ͜ͱʹΑͬͯɺॲཧϑϩʔΛ͍͘͢ͳͬͨ ར༻ଆɺػೳՃ࣌ʹؾʹ͖͢ࣄ͕ݮͬͨ Ҏલ͋ΒΏΔঢ়ଶΛ͋ΒΏΔॴͰཧ͍ͯͨ͠ "DUJPO 4UBUF 3FEVDFSͱ͕͚ΒΕ͍ͯΔҝɺ࣮ऀؒͷ༷ͷζϨ͕ܰݮ͞Εͨ
Copyright © 2017 eureka, Inc. All rights reserved.ϢʔβͷϨεϙϯεΛ࠷దԽ &ಡΈࠐΈͷߴԽ
Copyright © 2017 eureka, Inc. All rights reserved.31ϢʔβϨεϙϯεͷ࠷దԽ ͕͢͞ը໘ͰϦΫΤετͨ͠Ϣʔβใ͋ΒΏΔใΛؚΜͰ͍ͨ ֤ը໘Ͱ͏ҝͷϢʔβͷεςʔτͳͲ ϢʔβใΛੜ͢Δҝͷ༨ܭͳෛՙ͕αʔόαΠυʹ NTd
Copyright © 2017 eureka, Inc. All rights reserved.32ϢʔβϨεϙϯεͷ࠷దԽ ͕͢͞ը໘ͳͲɺ(SJE6*্Ͱදࣔ͢ΔϢʔβใʹඞཁ࠷ݶͳϨεϙϯεΛఆٛ ϢʔβϨεϙϯεΛʹ εϐʔυվળ NTNT
Copyright © 2017 eureka, Inc. All rights reserved.33ϢʔβՃಡΈࠐΈͷ࠷దԽ ҰʹԿ݅ϢʔβΛऔΓࠐΉ͔ɺϢʔβͷૢ࡞ΛͳΔ્͘͠ͳ͍MJNJUΛࢦఆ͍ͨ͠ ӈमਖ਼લ MJNJUΛ͗͢ΔͱಡΈࠐΈ͕ൃੜ͠ɺ͗͢ΔͱϨΠΞτߋ৽ʹӨڹ͢Δ ࠓͷॴ݅Λऔಘ͢Δͷ͕ྑͦ͞͏※ Ϣʔβը૾σϞ༻ʹ༻ҙͨ͠ͷʹͳΓ·͢
Copyright © 2017 eureka, Inc. All rights reserved.34ϢʔβՃಡΈࠐΈͷ࠷దԽ ՃಡΈࠐΈͷऔಘλΠϛϯάมߋ ࠓ·Ͱϖʔδखલ͔ΒϦΫΤετϢʔβΛྲྀ͠ಡΈ͍ͯ͠Δ߹ʹҾ͔͔ͬΓ͕͋ͬͨ dϖʔδखલ͙Β͍͔ΒϦΫΤετ͢Δͷ͕Αͦ͞͏ʁ
Copyright © 2017 eureka, Inc. All rights reserved.35ը૾ಡΈࠐΈߴԽ ը૾ͷಡΈࠐΈͷվળ ը૾ͷಡΈࠐΈλΠϛϯάͷݟ͠
Copyright © 2017 eureka, Inc. All rights reserved.36ը૾ಡΈࠐΈߴԽ with Nuke LFBO/VLFͷಋೖ Ұ௨Γͷػೳඋ ,JOHpTIFSͱൺͯߴ $BDIF3FRVFTUपΓͷΧελϚΠζ͕͍͢͠※ https://qiita.com/H_Crane/items/422811dfc18ae919f8a4
Copyright © 2017 eureka, Inc. All rights reserved.37ը૾ಡΈࠐΈߴԽ with Nukehttps://github.com/kean/Image-Frameworks-Benchmark
Copyright © 2017 eureka, Inc. All rights reserved.38ը૾ಡΈࠐΈߴԽ with Nukehttps://github.com/kean/Image-Frameworks-Benchmark
Copyright © 2017 eureka, Inc. All rights reserved.39ը૾ಡΈࠐΈߴԽ with NukeNuke.loadImage(with: ImageRequest(url: url),options: ImageLoadingOptions(transition: .fadeIn(duration: 0.33)),into: imageView)// That’s it!
Copyright © 2017 eureka, Inc. All rights reserved.40Nuke with Prefetch API J04͔Β6*$PMMFDUJPO7JFX%BUB4PVSDF1SFGFUDIJOH͕͑Δ 1SFGFUDIJOH/VLF*NBHF1SFIFBUFS XJMM%JTQMBZGPS*UFN"UͰ͍ͯͨ͠ը૾ߋ৽ΛDFMM'PS*UFN"UͰߦ͏Α͏ʹมߋ J04͔ΒݺΕΔλΠϛϯά͕มΘͬͨ ͱͷ͜ͱ͚ͩͲɾɾʁ
Copyright © 2017 eureka, Inc. All rights reserved.41Prefetching + Nuke.ImagePreheaterextension UserSearchViewController: UICollectionViewDataSourcePrefetching {fileprivate let preheater: Nuke.ImagePreheaterfunc collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths:[IndexPath]) {DispatchQueue(label: "scene.discovery.vc.prefetch").async { [weak self] inlet requests: [Nuke.ImageRequest] = indexPaths.map({..})self?.preheater.startPreheating(with: requests)}}func collectionView(_ collectionView: UICollectionView,cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {preheater.stopPreheating()}}
Copyright © 2017 eureka, Inc. All rights reserved.42Prefetching + Nuke.ImagePreheaterextension UserSearchViewController: UICollectionViewDataSourcePrefetching {fileprivate let preheater: Nuke.ImagePreheaterfunc collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths:[IndexPath]) {DispatchQueue(label: "scene.discovery.vc.prefetch").async { [weak self] inlet requests: [Nuke.ImageRequest] = indexPaths.map({..})self?.preheater.startPreheating(with: requests)}}func collectionView(_ collectionView: UICollectionView,cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {preheater.stopPreheating()}}
Copyright © 2017 eureka, Inc. All rights reserved.43Prefetching + Nuke.ImagePreheaterextension UserSearchViewController: UICollectionViewDataSourcePrefetching {fileprivate let preheater: Nuke.ImagePreheaterfunc collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths:[IndexPath]) {DispatchQueue(label: "scene.discovery.vc.prefetch").async { [weak self] inlet requests: [Nuke.ImageRequest] = indexPaths.map({..})self?.preheater.startPreheating(with: requests)}}func collectionView(_ collectionView: UICollectionView,cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {preheater.stopPreheating()}}
Copyright © 2017 eureka, Inc. All rights reserved.44ҙ 1SFGFUDI"1* දࣔ༧ఆͷͯ͢ͷ*OEFY1BUI͕͞ΕΔ༁Ͱͳ͍ DFMM'PS*UFN"U 1BJSTͷڥͰ΄΅XJMM%JTQMBZGPS*UFN"Uͱಉ͡λΠϛϯάͩͬͨ Կ͔͠Βͷ͕ඞཁ͔
Copyright © 2017 eureka, Inc. All rights reserved.45ϢʔβͷϨεϙϯε࠷దԽ & ը૾ಡΈࠐΈߴԽ ࠓ·Ͱͷഒऔಘεϐʔυ͕ૣ͍ҝɺϦϑϨογϡɺՃಡΈࠐΈ࣌ͷετϨεΛܰݮ ը૾ΛεΫϩʔϧ࣌ʹ͙֬͢ೝͰ͖ΔͨΊɺϢʔβ͕͙͢ʹΞΫγϣϯͰ͖ΔΑ͏ʹͳͬͨ
Copyright © 2017 eureka, Inc. All rights reserved.ࢦͤ60fps
60fpsͰψϧψϧମݧΛఏڙ͍ͨ͠
Copyright © 2017 eureka, Inc. All rights reserved.49AutoLayout߈Ͱ͞ͳ͚ΕͳΒͳ͍ ͔ͳΓޮՌ͕͋ͬͨ ମײ ͳͥͬͯͳ͔ͬͨ
Copyright © 2017 eureka, Inc. All rights reserved.50Fix AutoLayout tips ·ͣͳ͓͖͢$POTUSBJOUΛผ͢Δ /4-BZPVU$POTUSBJOUJEFOUJpFS 7JFX%FCVHHFS 3FWFBM
Copyright © 2017 eureka, Inc. All rights reserved.51Fix AutoLayout tips - NSLayoutConstraint.identifier /4-BZPVU$POTUSBJOUʹJEFOUJpFS͕ઃఆՄೳ ίʔυ্ͰઃఆՄ
Copyright © 2017 eureka, Inc. All rights reserved.52Fix AutoLayout tips - NSLayoutConstraint.identifier
Copyright © 2017 eureka, Inc. All rights reserved.53Fix AutoLayout tips - View Debugger
Copyright © 2017 eureka, Inc. All rights reserved.54Fix AutoLayout tips - Reveal 3FWFBMͰಉ༷ʹ/4-BZPVU$POTUSBJOU7JFXΛΞυϨεͰݕࡧՄೳ յΕ੍͍ͯͨΛϚʔΫͯ͘͠ΕΔҝݟ͍͢
AutoLayout͕յΕͨ߹߈Ͱ͠·͠ΐ͏
Copyright © 2017 eureka, Inc. All rights reserved.56Color Blended Layers 7JFX -BZFSΛॏͶͯඳը͍ͯ͠Δ෦ ॏͳΓ߹͏ϨΠϠʔΛൺֱ͠࠷ऴతͳग़ྗΛܭࢉ͢ΔҝɺඳըύϑΥʔϚϯεʹӨڹ͢Δ
Copyright © 2017 eureka, Inc. All rights reserved.57Color Blended Layers ֬ೝํ๏ 4JNVMBUPSͷ߹ .FOV$PMPS#MFOEFE-BZFSTʹνΣοΫ
Copyright © 2017 eureka, Inc. All rights reserved.58Color Blended Layers ֬ೝ ࣮ػͷ߹ 9DPEF 9DPEF%FCVH7JFX%FCVHHJOH3FOEFSJOH$PMPS#MFOEFE-BZFSTʹνΣοΫ
Copyright © 2017 eureka, Inc. All rights reserved.59Color Blended Layers ରࡦ - UIImageView Ͱ͖ΔݶΓCBDLHSPVOE$PMPSΛࢦఆ͢Δ ಁաը૾ΛͳΔ͘Θͳ͍ ະಁաͷΑ͏ͳը૾ͰBMQIBؚ͕·Ε͍ͯΔ߹͕͋ΔͨΊҙ
Copyright © 2017 eureka, Inc. All rights reserved.60Color Blended Layers ରࡦ - UILabel Ͱ͖ΔݶΓCBDLHSPVOE$PMPSΛࢦఆ͢Δ DMJQT5P#PVOETΛUSVFʹ ຊޠɾதࠃޠͳͲΛදࣔ͢Δ߹ɺڪΒ͘TVCMBZFS͕Ճ͞Ε͍ͯΔҝ ˞EFTDFOU͕ਖ਼͘͠ઃఆ͞Ε͍ͯΔTZTUFN'POUʹݶΔ
Copyright © 2017 eureka, Inc. All rights reserved.61Color Blended Layers ରࡦ - UILabelSystem Font + clipsToBounds HirakakuProN-W3 + clipsToBounds MFBEJOHΛແࢹͯ͠DMJQ͍ͯ͠Δhttps://speakerdeck.com/satoshin21/uifontdescriptor?slide=8leadingͳͲʹ͍ͭͯɺҎલpotatotipsͰൃදͨ͠ࢿྉΛ͝ࢀߟʹ͍ͯͩ͘͠͞
Copyright © 2017 eureka, Inc. All rights reserved.62Offscreen Rendering ؙ֯ӨΛεΫϦʔϯ্ʹඳը͢ΔࡍɺϨϯμϦϯάલʹલͬͯ ΦϑεΫϦʔϯͰॲཧΛߦ͏ ϋʔυΣΞΞΫηϥϨʔγϣϯ (16Λ༻͍ͯ͠ͳ͍ҝύϑΥʔϚϯεԼͷҰҼͱͳΔ SBTUFSJ[F͖͢λΠϛϯάͱ͖͢Ͱͳ͍λΠϛϯά͕͋Δ J04Ҏ߱Ͱ6**NBHF7JFXͰ࠷దԽ͞Ε͍ͯΔͱ͍͏͕ᷚͩɾɾ
Copyright © 2017 eureka, Inc. All rights reserved.63Offscreen Rendering - ֬ೝํ๏ $PMPS#MFOEFE-BZFSTͱಉ͡ํࣜͰ0⒎TDSFFO3FOEFSJOHΛ࣮ߦ͍ͯ͠ΔՕॴΛ৭͚Ͱ͖Δ
Copyright © 2017 eureka, Inc. All rights reserved.64Offscreen Rendering - ରࡦ ؙ֯༻ͷ.BTL7JFXΛ6**NBHF7JFXͷ্ʹͤΔํࣜͰ0⒎TDSFFO3FOEFSJOHΛආ͚͍ͯΔ վमલ͔Βߦ͍ͬͯΔҝɺৄࡉׂѪ ฐࣾͷϒϩάΛࢀর͍ͯͩ͘͠͞https://medium.com/eureka-engineering/iosͷϋΠύϑΥʔϚϯεͳcorner-rounding-strategy-88a43641b554
Copyright © 2017 eureka, Inc. All rights reserved.65ࠩߋ৽ ݱࡏՃಡΈࠐΈɺ1VMMUP3FGSFTI͢ΔͨͼʹDPMMFDUJPO7JFXSFMPBE%BUB ΛݺΜͰ͍ͨ SFMPBE%BUB ΛݺͿ͜ͱͰෆඞཁͳWJTJCMF$FMMTͷߋ৽͕࣮ߦ͞ΕΔ
Copyright © 2017 eureka, Inc. All rights reserved.66ࠩߋ৽ - Libraries *OTUBHSBN*(-JTU,JU TFDUJPOϕʔεͷࠩൺֱ 3Y4XJGU$PNNVOJUZ3Y%BUB4PVSDFT KqJOUFS%XJ⒎U NVVLJJ%BUB4PVSDFT
Copyright © 2017 eureka, Inc. All rights reserved.67muukii/DataSources NVVLJJ%BUB4PVSDFT *(-JTU,JUͳͲͷࠩநग़ΞϧΰϦζϜΛࢀߟʹ࡞ΒΕ͍ͯΔ λΠϓηʔϑ ࠩநग़ʹಛԽͨ͠γϯϓϧͳΈطଘͷΈͱੑ͕ߴ͍ ฐࣾϝϯόʔ NVVLJJ͕࡞͍ͬͯΔҝɺ࣭͕͋ͬͨΒ͙͢ฉ͚Δ
Copyright © 2017 eureka, Inc. All rights reserved.68muukii/DataSources - ModelΛఆٛenum Item {case user(User)case banner(Banner)case feature(Feature) // ϨίϝϯυͷΑ͏ͳͷ}
Copyright © 2017 eureka, Inc. All rights reserved.69muukii/DataSources - ModelΛఆٛimport DataSourcesextension Item: DataSources.Diffable {typealias Identifier = Stringvar diffIdentifier: String {switch self {case .user(let user): return user.diffIdentifiercase .banner(let banner): return banner.diffIdentifiercase .feature(let feature): return feature.diffIdentifier}}}
Copyright © 2017 eureka, Inc. All rights reserved.70muukii/DataSources - ModelΛఆٛimport DataSourcesextension Item: DataSources.Diffable {typealias Identifier = Stringvar diffIdentifier: String {switch self {case .user(let user): return user.diffIdentifiercase .banner(let banner): return banner.diffIdentifiercase .feature(let feature): return feature.diffIdentifier}}}
Copyright © 2017 eureka, Inc. All rights reserved.71muukii/DataSources - ModelΛఆٛimport DataSourcesextension Item: DataSources.Diffable {typealias Identifier = Stringvar diffIdentifier: String {switch self {case .user(let user): return user.diffIdentifiercase .banner(let banner): return banner.diffIdentifiercase .feature(let feature): return feature.diffIdentifier}}}
Copyright © 2017 eureka, Inc. All rights reserved.72muukii/DataSources - SectionControllerΛఆٛfinal class UserSearchViewController: UIViewController, StoreSubscriber {fileprivate lazy var sectionController:DataSources.SectionDataController = .init(adapter: .init(collectionView: self.collectionView),displayingSection: 0,isEqual: { a, b in a.diffIdentifier == b.diffIdentifier })}
Copyright © 2017 eureka, Inc. All rights reserved.73muukii/DataSources - SectionControllerΛఆٛfinal class UserSearchViewController: UIViewController, StoreSubscriber {fileprivate lazy var sectionController:DataSources.SectionDataController = .init(adapter: .init(collectionView: self.collectionView),displayingSection: 0,isEqual: { a, b in a.diffIdentifier == b.diffIdentifier })}
Copyright © 2017 eureka, Inc. All rights reserved.74muukii/DataSources - SectionControllerΛఆٛfinal class UserSearchViewController: UIViewController, StoreSubscriber {fileprivate lazy var sectionController:DataSources.SectionDataController = .init(adapter: .init(collectionView: self.collectionView),displayingSection: 0,isEqual: { a, b in a.diffIdentifier == b.diffIdentifier })}
Copyright © 2017 eureka, Inc. All rights reserved.75muukii/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")})}}}
Copyright © 2017 eureka, Inc. All rights reserved.76muukii/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")})}}}
Copyright © 2017 eureka, Inc. All rights reserved.77muukii/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")})}}}
60fpsʹ͚ۙͮͨͷ͔ʁ
ߋ৽લ ߋ৽ޙiPhone 5(MD297J/A) iOS 10.3.3※ Ϣʔβը૾σϞ༻ʹ༻ҙͨ͠ͷʹͳΓ·͢
ߋ৽લ ߋ৽ޙ36fps60fps55fpsiPhone 5(MD297J/A) iOS 10.3.3※ Ϣʔβը૾σϞ༻ʹ༻ҙͨ͠ͷʹͳΓ·͢
Copyright © 2017 eureka, Inc. All rights reserved.·ͱΊ
Copyright © 2017 eureka, Inc. All rights reserved.82վળ݁Ռ ਓؒʹཧղ͕͔ͬͨ͠ॲཧϑϩʔΛ3FEVYΛಋೖ͢Δ͜ͱͰΘ͔Γ͘͢ఆٛ͢Δ͜ͱ͕Ͱ͖ͨ ৮͍ͬͯͯ৺͍͍6*69Λఏڙ͢Δϕʔε͕Ͱ͖ͨ GQTΛҰͭͷࢦඪͱ͢Δ͜ͱͰɺ6*69্ΛఆྔԽ͢Δ͜ͱ͕Ͱ͖ͨ
Copyright © 2017 eureka, Inc. All rights reserved.83օ͞Μʹ͓ئ͍ ΤϨΧϒʔεΛ༻ҙ͍ͯ͠·͢ʂ ͠ɺύϑΥʔϚϯενϡʔχϯάʹؔͯ͠ڵຯ͕͋Δํɺʮ͜ΕΛվળͨ͠ΒύϑΥʔϚϯε্ͨ͠ΑʂʯͳͲͷϊϋ͕͋ΔํͳͲ͍Βͬ͠Ό͍·ͨ͠Βɺੋඇͱใަ͠·͠ΐ͏
Thank youIUUQTXXXOBTBHPWNJTTJPO@QBHFT/11OFXTFBSUIBUOJHIUIUNM