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

安定的 60 fps をめざす / the way to 60 fps

Taishi Ikai
January 29, 2018

安定的 60 fps をめざす / the way to 60 fps

iOS app
at Otemachi.swift x Kyobashi.swift #02
https://kyobashi-swift.connpass.com/event/75379/

Taishi Ikai

January 29, 2018
Tweet

More Decks by Taishi Ikai

Other Decks in Technology

Transcript

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

    View Slide

  2. <ಈը>

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. 8
    UITableView ͷଓ͖ΛಡΉͱ͖ͳͲɺUITableView ʹηϧΛ௥Ճ͢Δલʹɺ

    ઌʹߴ͞Λܭࢉ͓ͯ͘͠ & ΦϑεΫϦʔϯඳըͪ͠Ό͏
    ϝϞϦޮ཰ͷ఺Ͱ͸ɺඍົ͔΋͠Εͳ͍?
    ༧Ί΍Δ

    View Slide

  9. ۩ମతʹ
    9

    View Slide

  10. UITableViewCell Λܧঝ͢ΔΫϥεͰ
    init() ͳͲͰ UILabel, UIImageView Λ contentView ʹ௥Ճ
    Constraints, StackView Λ͔ͭͬͯ഑ஔ
    cellForRow(at indexPath:) ͷதͰ
    dequeueReusableCell(withIdentifier identifier:, for indexPath:) Ͱ

    ηϧΛऔಘ
    (όοΫάϥ΢ϯυͰ) ը૾Λऔಘͯ͠ UIImageView ʹ౉͢
    ηϧͷཁૉ͕૿͑Δʹ࿈Εͯɺॏ͘ͳͬͯ͘Δ
    10
    UITableView Ͱͷσʔλදࣔ

    View Slide

  11. UITableViewCell Λܧঝ͢ΔΫϥεͰ
    init() ͳͲͰ UILabel, UIImageView Λ contentView ʹ௥Ճ
    Constraints, StackView Λ͔ͭͬͯ഑ஔ
    cellForRow(at indexPath:) ͷதͰ
    dequeueReusableCell(withIdentifier identifier:, for indexPath:) Ͱ

    ηϧΛऔಘ
    (όοΫάϥ΢ϯυͰ) ը૾Λऔಘͯ͠ UIImageView ʹ౉͢
    ηϧͷཁૉ͕૿͑Δʹ࿈Εͯɺॏ͘ͳͬͯ͘Δ
    11
    UITableView Ͱͷσʔλදࣔ

    View Slide

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

    View Slide

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

    NSString, NSAttributedString ͷ boundingRect Λར༻
    Ϩϕϧ1: खಈϨΠΞ΢τ + Auto Resizing Mask

    View Slide

  14. 14
    UILabel, UIImageView Λ࢖ΘͣʹɺखಈͰඳը͢Δ
    શͯखಈͰϨΠΞ΢τ
    UIView (, UITableViewCell) ͷ draw(_:) Λ্ॻ͖ͯ͠ɺ

    NSString, NSAttributedString ͷ draw ܥͰॻ͖ࠐΉ
    NSAttributedString ͸ɺόοΫάϥ΢ϯυͰ૷০͓ͯ͘͠
    Ϩϕϧ2: ௚઀ඳ͘

    View Slide

  15. 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()
    }

    View Slide

  16. 16
    UILabel, UIImageView Λ࢖ΘͣʹɺखಈͰඳը͢Δ
    drawRect ͤͣʹɺόοΫάϥ΢ϯυͰ UIGraphicsBeginImageContextWithOptions

    ͯ͠ɺίϯςΩετΛ࡞Γɺͦ͜ʹॻ͖ࠐΉ
    ࠷ऴతʹ͸ɺඳըྖҬͷ CGImage Λ࡞͓͍ͬͯͯɺ

    ͦΕΛΩϟογϡ͓ͯ͘͠
    ॾʑͷॲཧΛ࣮֬ʹόοΫάϥ΢ϯυʹ

    ࿈Ε͍͚ͯΔͱ͍͏ϝϦοτ
    Ϩϕϧ3: CGImage ΛόοΫάϥ΢ϯυͰͭͬͯ͘షΔ

    View Slide

  17. 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 ʹషΔ

    View Slide

  18. 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 Λͳ͘͢

    View Slide

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

    View Slide

  20. Pinterest ͷਓ͕ͨͪத৺ʹ։ൃ͍ͯ͠Δඇಉظతͷ UI ඳըϑϨʔϜϫʔΫ

    RxSwift ͱ૊Έ߹Θͤͯ࢖͏ࣄྫ͕গͳ͔ͬͨ &

    View ·ΘΓ૯ͱ͔͕ͬ͑ඞཁͦ͏ͩͬͨͷͰݟૹͬͨ
    "Native" Ͱ͋Δҙٛͱͯ͠ 60 fps ͷୡ੒Λҙ͍ࣝͯ͠Δ

    Core Text ͳͲ௿ϨΠϠʔͳ API ʹ΋ׂΓͱ৮͍ͬͯͨ &

    ஌ݟ͕গͳ͘ϦϦʔε೔ʹؒʹ߹ΘͤΔࣗ৴͕࣋ͯͣɺݟૹͬͨ
    20
    ࠓޙݕ౼͍ͨ͠
    چ໊শ: AsyncDisplayKit

    View Slide

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

    View Slide