iOS app at Otemachi.swift x Kyobashi.swift #02 https://kyobashi-swift.connpass.com/event/75379/
1҆ఆత 60 fps ΛΊ͟͢ழࣂ େࢤ ຊܦࡁ৽ฉࣾOtemachi.swift x Kyobashi.swift #02
View Slide
<ಈը>
3FPS Frames Per Second ͷུ1 ඵؒʹදࣔ͢ΔϑϨʔϜ͜Ε͕େ͖͍ͱɺΒ͔ʹݟ͑ΔʢňψϧψϧʼnײɺUX ʹӨڹ͢ΔԾઆʣUIScreen.main.maximumFramesPerSecond࠷େ FPS Λऔಘ͢ΔɻiOS σόΠεͰɺ௨ৗ 60ϝΠϯεϨουͰߦ͏ॲཧͷͱॏ͞ΛۃྗݮΒͯ͠ɺ࣮ݱΛࢦ͢ࠓ͔ΒɺҰൠతͳઓུͱɺView ଆʹϑΥʔΧεͨ͠Λ͠·͢FPS ʹ͍ͭͯ
4ඞཁͳ͜ͱ͚ͩ͢ΔUIεϨουΛܰ͘͢ΔɺϒϩοΫ͠ͳ͍Կ͠ͳ͍͘͢Δ༧ΊΔ→ Instruments Λݟͳ͕Βɺॏ͍ͱ͜Ζ͔ΒରԠΛ͍ͯ͘͠FPS ࢹʹΑΔ֬ೝɺInstruments ͷ Core Animation Ͱ֬ೝՄೳͳݶΓݹ͍Λར༻ํ
5ͦͷ࣌ͰෆཁͳσʔλΛ֎͍ͬͯ͢ͳ͍ϩδοΫΛফ֤͢ͰΔඞཁ͕͋Δͷ͚ͩड͚औΔͲͷͰಉ͡ॲཧʹͳΔͳΒɺ API Ͱܗ͓ͯ͘͠unixtime Ͱड͚औΔͳͲͲ͏ͯ͠ UI εϨου͡Όͳ͍ͱͰ͖ͳ͍͜ͱ͚ͩΔ❌ ௨৴σΟεΫॻ͖ࠐΈ❌ NSAttributedString ͷੜɺηϧͷߴ͞ͷܭࢉɺΦϑεΫϦʔϯඳըඞཁͳ͜ͱ͚ͩΔ
6UITableViewCell, UITableView(Header|Footer)View ͳͲ࠶ར༻͢ΔεΫϩʔϧͷͨͼʹੜ͢Δͱ݁ߏॏ͍ϖʔδ UI ͳΒɺVC ࠶ར༻Ͱ͖Δͱྑͦ͞͏ಉ͡ΧϥʔɺϑΥϯτɺਖ਼نදݱɺϑΥʔϚολʔ࠶ར༻͢ΔUIColor, UIFont, NSRegularExpression, DateFormatter, NumberFormatterຖੜ͢Δඞཁͳ͚ΕఆԽ͢ΔɺΩϟογϡ͢ΔComputed property ຖճධՁ͞ΕΔνϦπϞͰ݁ߏͳϘτϧωοΫʹͳ͍ͬͯΔ͜ͱԿ͠ͳ͍
7ߴͳ DBɺΩϟογϡɺπʔϧΛ͏Realm ͳͲंྠͷ࠶ൃ໌͍ͯ͠ͳ͍͔UITableViewCell ͷߴ͞ܭࢉɺcell ͷͳͲɺԆͤ͞ʹ͍͘ؤுͬͯ͘Δɺࣄલʹϩʔυ͢Δ͘Δ
8UITableView ͷଓ͖ΛಡΉͱ͖ͳͲɺUITableView ʹηϧΛՃ͢Δલʹɺ ઌʹߴ͞Λܭࢉ͓ͯ͘͠ & ΦϑεΫϦʔϯඳըͪ͠Ό͏ϝϞϦޮͷͰɺඍົ͔͠Εͳ͍?༧ΊΔ
۩ମతʹ9
UITableViewCell Λܧঝ͢ΔΫϥεͰinit() ͳͲͰ UILabel, UIImageView Λ contentView ʹՃConstraints, StackView Λ͔ͭͬͯஔcellForRow(at indexPath:) ͷதͰdequeueReusableCell(withIdentifier identifier:, for indexPath:) Ͱ ηϧΛऔಘ(όοΫάϥϯυͰ) ը૾Λऔಘͯ͠ UIImageView ʹ͢ηϧͷཁૉ͕૿͑Δʹ࿈Εͯɺॏ͘ͳͬͯ͘Δ10UITableView Ͱͷσʔλදࣔ
UITableViewCell Λܧঝ͢ΔΫϥεͰinit() ͳͲͰ UILabel, UIImageView Λ contentView ʹՃConstraints, StackView Λ͔ͭͬͯஔcellForRow(at indexPath:) ͷதͰdequeueReusableCell(withIdentifier identifier:, for indexPath:) Ͱ ηϧΛऔಘ(όοΫάϥϯυͰ) ը૾Λऔಘͯ͠ UIImageView ʹ͢ηϧͷཁૉ͕૿͑Δʹ࿈Εͯɺॏ͘ͳͬͯ͘Δ11UITableView Ͱͷσʔλදࣔ
12҆ఆత 60 fps Λ࣮ݱ͢ΔʹɺAuto Layoutɺ Stack View Ͱ͍͠ൺֱత৽͍͠Ͱɺཁૉ (view) ͕ଟ͘ͳΔͱΧΫ͍ͭͯ͘Δಛʹຊޠ͕ೖΔͱɺϑΥϯτબ Auto LayoutɺखಈϨΠΞτͷਏΈηϧͷߴ͞ܭࢉΛࣗͰߦ͏Ϩϕϧ 1 → 3 ʹ͚͓ͯ͠͠·͢Auto Layout ΛΊΔ
13UILabel, UIImageView ͷ frame ΛࣗͰܭࢉͯ͠ஔ͍ͯ͘͠߹ʹΑͬͯ Auto Resizing Mask Λར༻Auto Layout Ҏલͷ࣌ͰओྲྀίʔυߦׂΓͱ૿Ճߴ͞ܭࢉखಈUILabel, UIImageView ϝΠϯεϨουͰ৮ΕΔඞཁ͕͋ΔͷͰɺ NSString, NSAttributedString ͷ boundingRect Λར༻Ϩϕϧ1: खಈϨΠΞτ + Auto Resizing Mask
14UILabel, UIImageView ΛΘͣʹɺखಈͰඳը͢ΔશͯखಈͰϨΠΞτUIView (, UITableViewCell) ͷ draw(_:) Λ্ॻ͖ͯ͠ɺ NSString, NSAttributedString ͷ draw ܥͰॻ͖ࠐΉNSAttributedString ɺόοΫάϥϯυͰ০͓ͯ͘͠Ϩϕϧ2: ඳ͘
15override func draw(_ rect: CGRect) {guard let context = UIGraphicsGetCurrentContext() else { return nil }var remainRect = rectvar 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.heightremainRect.size.height -= attributedStringRect.bounds.height//// ཁૉͷ܁Γฦ͢//UIGraphicsEndImageContext()}
16UILabel, UIImageView ΛΘͣʹɺखಈͰඳը͢ΔdrawRect ͤͣʹɺόοΫάϥϯυͰ UIGraphicsBeginImageContextWithOptions ͯ͠ɺίϯςΩετΛ࡞Γɺͦ͜ʹॻ͖ࠐΉ࠷ऴతʹɺඳըྖҬͷ CGImage Λ࡞͓͍ͬͯͯɺ ͦΕΛΩϟογϡ͓ͯ͘͠ॾʑͷॲཧΛ࣮֬ʹόοΫάϥϯυʹ ࿈Ε͍͚ͯΔͱ͍͏ϝϦοτϨϕϧ3: CGImage ΛόοΫάϥϯυͰͭͬͯ͘షΔ
17Func 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 ʹషΔ
18UIView Ͱ backgroundColor Λ୯৭ʹ UIView Ͱ opaque: trueޮՌ͋·Γ࣮ײͰ͖ͣ...> Blended view layers often cause slow table scrolling. https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/MeasuringGraphicsPerformance.htmlBlended Layers Λͳ͘͢
ϝΠϯεϨουΛۃྗΘͳ͍ҙ͕ࣝॏཁόοΫάϥϯυͰ CGImage ʹॻ͖ࠐΉͷޮՌ͋ͬͨඳըʹؔΘΔॲཧΛશͯόοΫάϥϯυʹ͍͚ͬͯͨ͘ͳΓ͗͢Δͱന͍ηϧ͕ը໘ʹͰͯ͘ΔAuto Layout, StackView Ίͯɺ͍ͩͿૣ͘ͳͬͨখ͍͞Օॴ͕ੵͬͯҾ͔͔ͬΔ͜ͱ͕ଟʑ͋ͬͨNSAttributedString UIFont ͰΩϟογϡ͔ఆԽ19·ͱΊ20%10%40%30%खಈϨΠΞτCGImageνϦ
Pinterest ͷਓ͕ͨͪத৺ʹ։ൃ͍ͯ͠Δඇಉظతͷ UI ඳըϑϨʔϜϫʔΫ RxSwift ͱΈ߹Θͤͯ͏ࣄྫ͕গͳ͔ͬͨ & View ·ΘΓ૯ͱ͔͕ͬ͑ඞཁͦ͏ͩͬͨͷͰݟૹͬͨ"Native" Ͱ͋Δҙٛͱͯ͠ 60 fps ͷୡΛҙ͍ࣝͯ͠Δ Core Text ͳͲϨΠϠʔͳ API ʹׂΓͱ৮͍ͬͯͨ & ݟ͕গͳ͘ϦϦʔεʹؒʹ߹ΘͤΔࣗ৴͕࣋ͯͣɺݟૹͬͨ20ࠓޙݕ౼͍ͨ͠چ໊শ: AsyncDisplayKit
21ழࣂ େࢤʢ͍͔͍ ͍ͨ͠ʣຊܦࡁ৽ฉࣾॴଐͷΤϯδχΞ͍ͭͬͯ͘Δͷ:iPhone ͷܦిࢠ൛ΞϓϦiPhone / iPad ͷࢴ໘ϏϡʔΞʔΞϓϦΞϓϦͷόοΫΤϯυܥ (w/αʔόʔϨε)About me