Slide 1

Slide 1 text

1 ҆ఆత 60 fps ΛΊ͟͢ ழࣂ େࢤ ೔ຊܦࡁ৽ฉࣾ Otemachi.swift x Kyobashi.swift #02

Slide 2

Slide 2 text

<ಈը>

Slide 3

Slide 3 text

3 FPS ͸ Frames Per Second ͷུ 1 ඵؒʹදࣔ͢ΔϑϨʔϜ਺ ͜Ε͕େ͖͍ͱɺ׈Β͔ʹݟ͑ΔʢňψϧψϧʼnײɺUX ʹӨڹ͢ΔԾઆʣ UIScreen.main.maximumFramesPerSecond ࠷େ FPS Λऔಘ͢ΔɻiOS σόΠεͰ͸ɺ௨ৗ 60 ϝΠϯεϨουͰߦ͏ॲཧͷ਺ͱॏ͞ΛۃྗݮΒͯ͠ɺ࣮ݱΛ໨ࢦ͢ ࠓ͔Β͸ɺҰൠతͳઓུͱɺView ଆʹϑΥʔΧεͨ͠࿩Λ͠·͢ FPS ʹ͍ͭͯ

Slide 4

Slide 4 text

4 ඞཁͳ͜ͱ͚ͩ͢Δ UIεϨουΛܰ͘͢ΔɺϒϩοΫ͠ͳ͍ Կ౓΋͠ͳ͍ ଎͘͢Δ ༧Ί΍Δ → Instruments Λݟͳ͕Βɺॏ͍ͱ͜Ζ͔ΒରԠΛ͍ͯ͘͠ FPS ͸໨ࢹʹΑΔ֬ೝɺInstruments ͷ Core Animation Ͱ֬ೝ ՄೳͳݶΓݹ͍୺຤Λར༻ ํ਑

Slide 5

Slide 5 text

5 ͦͷ࣌఺ͰෆཁͳσʔλΛ֎͢ ࢖͍ͬͯͳ͍ϩδοΫΛফ͢ ֤୺຤Ͱ΍Δඞཁ͕͋Δ΋ͷ͚ͩड͚औΔ Ͳͷ୺຤Ͱ΋ಉ͡ॲཧʹͳΔͳΒɺ API Ͱ੔ܗ͓ͯ͘͠ unixtime Ͱड͚औΔͳͲ Ͳ͏ͯ͠΋ UI εϨου͡Όͳ͍ͱͰ͖ͳ͍͜ͱ͚ͩ΍Δ ❌ ௨৴΍σΟεΫॻ͖ࠐΈ ❌ NSAttributedString ͷੜ੒ɺηϧͷߴ͞ͷܭࢉɺΦϑεΫϦʔϯඳը ඞཁͳ͜ͱ͚ͩ΍Δ

Slide 6

Slide 6 text

6 UITableViewCell, UITableView(Header|Footer)View ͳͲ͸࠶ར༻͢Δ εΫϩʔϧͷͨͼʹੜ੒͢Δͱ݁ߏॏ͍ ϖʔδ UI ͳΒɺVC ΋࠶ར༻Ͱ͖Δͱྑͦ͞͏ ಉ͡ΧϥʔɺϑΥϯτɺਖ਼نදݱɺϑΥʔϚολʔ͸࠶ར༻͢Δ UIColor, UIFont, NSRegularExpression, DateFormatter, NumberFormatter ຖ౓ੜ੒͢Δඞཁͳ͚Ε͹ఆ਺Խ͢ΔɺΩϟογϡ͢Δ Computed property ͸ຖճධՁ͞ΕΔ νϦπϞͰ݁ߏͳϘτϧωοΫʹͳ͍ͬͯΔ͜ͱ΋ Կ౓΋͠ͳ͍

Slide 7

Slide 7 text

7 ߴ଎ͳ DBɺΩϟογϡɺπʔϧΛ࢖͏ Realm ͳͲ ंྠͷ࠶ൃ໌͍ͯ͠ͳ͍͔ UITableViewCell ͷߴ͞ܭࢉɺcell ͷ਺ͳͲ͸ɺ஗Ԇͤ͞ʹ͍͘ ؤுͬͯ଎͘΍Δɺࣄલʹϩʔυ͢Δ ଎͘΍Δ

Slide 8

Slide 8 text

8 UITableView ͷଓ͖ΛಡΉͱ͖ͳͲɺUITableView ʹηϧΛ௥Ճ͢Δલʹɺ
 ઌʹߴ͞Λܭࢉ͓ͯ͘͠ & ΦϑεΫϦʔϯඳըͪ͠Ό͏ ϝϞϦޮ཰ͷ఺Ͱ͸ɺඍົ͔΋͠Εͳ͍? ༧Ί΍Δ

Slide 9

Slide 9 text

۩ମతʹ 9

Slide 10

Slide 10 text

UITableViewCell Λܧঝ͢ΔΫϥεͰ init() ͳͲͰ UILabel, UIImageView Λ contentView ʹ௥Ճ Constraints, StackView Λ͔ͭͬͯ഑ஔ cellForRow(at indexPath:) ͷதͰ dequeueReusableCell(withIdentifier identifier:, for indexPath:) Ͱ
 ηϧΛऔಘ (όοΫάϥ΢ϯυͰ) ը૾Λऔಘͯ͠ UIImageView ʹ౉͢ ηϧͷཁૉ͕૿͑Δʹ࿈Εͯɺॏ͘ͳͬͯ͘Δ 10 UITableView Ͱͷσʔλදࣔ

Slide 11

Slide 11 text

UITableViewCell Λܧঝ͢ΔΫϥεͰ init() ͳͲͰ UILabel, UIImageView Λ contentView ʹ௥Ճ Constraints, StackView Λ͔ͭͬͯ഑ஔ cellForRow(at indexPath:) ͷதͰ dequeueReusableCell(withIdentifier identifier:, for indexPath:) Ͱ
 ηϧΛऔಘ (όοΫάϥ΢ϯυͰ) ը૾Λऔಘͯ͠ UIImageView ʹ౉͢ ηϧͷཁૉ͕૿͑Δʹ࿈Εͯɺॏ͘ͳͬͯ͘Δ 11 UITableView Ͱͷσʔλදࣔ

Slide 12

Slide 12 text

12 ҆ఆత 60 fps Λ࣮ݱ͢Δʹ͸ɺAuto Layoutɺ Stack View Ͱ͸೉͍͠ ൺֱత৽͍͠୺຤Ͱ΋ɺཁૉ (view) ͕ଟ͘ͳΔͱΧΫ͍ͭͯ͘Δ ಛʹ೔ຊޠ͕ೖΔͱɺϑΥϯτબ୒ ୤ Auto LayoutɺखಈϨΠΞ΢τͷਏΈ ηϧͷߴ͞ܭࢉΛࣗ෼Ͱߦ͏ Ϩϕϧ 1 → 3 ʹ෼͚͓ͯ࿩͠͠·͢ Auto Layout Λ΍ΊΔ

Slide 13

Slide 13 text

13 UILabel, UIImageView ͷ frame Λࣗ෼Ͱܭࢉͯ͠഑ஔ͍ͯ͘͠ ৔߹ʹΑͬͯ Auto Resizing Mask Λར༻ Auto Layout Ҏલͷ࣌୅Ͱ͸ओྲྀ ίʔυߦ਺͸ׂΓͱ૿Ճ ߴ͞ܭࢉ΋खಈ UILabel, UIImageView ͸ϝΠϯεϨουͰ৮ΕΔඞཁ͕͋ΔͷͰɺ
 NSString, NSAttributedString ͷ boundingRect Λར༻ Ϩϕϧ1: खಈϨΠΞ΢τ + Auto Resizing Mask

Slide 14

Slide 14 text

14 UILabel, UIImageView Λ࢖ΘͣʹɺखಈͰඳը͢Δ શͯखಈͰϨΠΞ΢τ UIView (, UITableViewCell) ͷ draw(_:) Λ্ॻ͖ͯ͠ɺ
 NSString, NSAttributedString ͷ draw ܥͰॻ͖ࠐΉ NSAttributedString ͸ɺόοΫάϥ΢ϯυͰ૷০͓ͯ͘͠ Ϩϕϧ2: ௚઀ඳ͘

Slide 15

Slide 15 text

15 override func draw(_ rect: CGRect) { guard let context = UIGraphicsGetCurrentContext() else { return nil } var remainRect = rect var attributedStringRect = self.attributedString.boundingRectCached( scope: "emblem", size: remainRect.size, options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine]) self.attributedString.draw( with: remainRect, options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil ) remainRect.origin.y += attributedStringRect.bounds.height remainRect.size.height -= attributedStringRect.bounds.height // // ཁૉͷ਺෼܁Γฦ͢ // UIGraphicsEndImageContext() }

Slide 16

Slide 16 text

16 UILabel, UIImageView Λ࢖ΘͣʹɺखಈͰඳը͢Δ drawRect ͤͣʹɺόοΫάϥ΢ϯυͰ UIGraphicsBeginImageContextWithOptions
 ͯ͠ɺίϯςΩετΛ࡞Γɺͦ͜ʹॻ͖ࠐΉ ࠷ऴతʹ͸ɺඳըྖҬͷ CGImage Λ࡞͓͍ͬͯͯɺ
 ͦΕΛΩϟογϡ͓ͯ͘͠ ॾʑͷॲཧΛ࣮֬ʹόοΫάϥ΢ϯυʹ
 ࿈Ε͍͚ͯΔͱ͍͏ϝϦοτ Ϩϕϧ3: CGImage ΛόοΫάϥ΢ϯυͰͭͬͯ͘షΔ

Slide 17

Slide 17 text

17 Func getImage(with bounds: CGSize) -> CGImage { if let image = CacheStore.get(/* ৚݅ */) { return image } // όοΫάϥ΢ϯυΩϡʔͰɺcontext Λ࡞੒ UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0) guard let context = UIGraphicsGetCurrentContext() else { return nil } // ࣗ෼Ͱߴ͞ܭࢉΛ͠ͳ͕ΒɺNSAttributedString ͷ draw ͳͲͰ context ʹॻ͖ࠐΜͰ͍͘ attributedString.draw(with: bounds, options: drawingOptions, context: nil) // ऴΘͬͨΒ makeImage() ͯ͠ context Λऴ͑Δ let image = context.makeImage() UIGraphicsEndImageContext() if let image = image { CacheStore.set(image, forKey: key) } return image } ը૾΋όοΫάϥ΢ϯυͰऔಘͯ͠ɺ
 CGLayer ͷ cgImage ʹషΔ

Slide 18

Slide 18 text

18 UIView Ͱ backgroundColor Λ୯৭ʹ
 UIView Ͱ opaque: true ޮՌ͸͋·Γ࣮ײͰ͖ͣ... > Blended view layers often cause slow table scrolling.
 https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/MeasuringGraphicsPerformance.html Blended Layers Λͳ͘͢

Slide 19

Slide 19 text

ϝΠϯεϨουΛۃྗ࢖Θͳ͍ҙ͕ࣝॏཁ όοΫάϥ΢ϯυͰ CGImage ʹॻ͖ࠐΉͷޮՌ͋ͬͨ ඳըʹؔΘΔॲཧΛશͯόοΫάϥ΢ϯυʹ΋͍͚ͬͯͨ ஗͘ͳΓ͗͢Δͱന͍ηϧ͕ը໘ʹͰͯ͘Δ Auto Layout, StackView ΍Ίͯɺ͍ͩͿૣ͘ͳͬͨ খ͍͞Օॴ͕ੵ΋ͬͯҾ͔͔ͬΔ͜ͱ͕ଟʑ͋ͬͨ NSAttributedString ΍ UIFont Ͱ΋Ωϟογϡ͔ఆ਺Խ 19 ·ͱΊ 20% 10% 40% 30% खಈϨΠΞ΢τ CGImage νϦ

Slide 20

Slide 20 text

Pinterest ͷਓ͕ͨͪத৺ʹ։ൃ͍ͯ͠Δඇಉظతͷ UI ඳըϑϨʔϜϫʔΫ
 RxSwift ͱ૊Έ߹Θͤͯ࢖͏ࣄྫ͕গͳ͔ͬͨ &
 View ·ΘΓ૯ͱ͔͕ͬ͑ඞཁͦ͏ͩͬͨͷͰݟૹͬͨ "Native" Ͱ͋Δҙٛͱͯ͠ 60 fps ͷୡ੒Λҙ͍ࣝͯ͠Δ
 Core Text ͳͲ௿ϨΠϠʔͳ API ʹ΋ׂΓͱ৮͍ͬͯͨ &
 ஌ݟ͕গͳ͘ϦϦʔε೔ʹؒʹ߹ΘͤΔࣗ৴͕࣋ͯͣɺݟૹͬͨ 20 ࠓޙݕ౼͍ͨ͠ چ໊শ: AsyncDisplayKit

Slide 21

Slide 21 text

21 ழࣂ େࢤʢ͍͔͍ ͍ͨ͠ʣ ೔ຊܦࡁ৽ฉࣾॴଐͷΤϯδχΞ ͍ͭͬͯ͘Δ΋ͷ: iPhone ͷ೔ܦిࢠ൛ΞϓϦ iPhone / iPad ͷࢴ໘ϏϡʔΞʔΞϓϦ ΞϓϦͷόοΫΤϯυܥ (w/αʔόʔϨε) About me