$30 off During Our Annual Pro Sale. View Details »

Embedded Frameworkのススメ

Go Takagi
October 16, 2018

Embedded Frameworkのススメ

Go Takagi

October 16, 2018
Tweet

More Decks by Go Takagi

Other Decks in Programming

Transcript

  1. 差分Buildでサクサク開発
    Embedded Frameworkのススメ
    ⾼⽊ 豪 ⽇本経済新聞社インターン
    Otemachi.swift #02

    View Slide

  2. ‣ Status
    • 東京⼯業⼤学 M2
    ‣ SNS
    • @shimastripe / @shimastriper / @root
    ‣ Intern Task (iOS)
    • 電⼦版の3d touch
    • Modulesをフレームワーク化 ←Now!!
    ‣ Fav Language
    • Go (は?)
    ✴ ⼿持ちのMBPはiOSのBuildが⻑くて⾟い
    Go Takagi
    2

    View Slide

  3. 翻訳「Buildを待つ僕」
    3

    View Slide

  4. 1. スペックで殴る
    • iMacProを購⼊しましょう
    2. プロダクトのボトルネックを減らす
    • 例えば型推論
    • 重複コンパイルを減らす
    • 差分Buildを促進したい

    Build時間改善⽅法
    4
    Embedded Framework !!

    View Slide

  5. ‣ Embedded Frameworkの紹介
    ‣ 電⼦版への導⼊に必要だったタスク
    ‣ Build時間改善した??
    Agenda
    5

    View Slide

  6. Embedded Framework

    View Slide

  7. ‣ Info
    • AppとExtension間でコード共有する埋め込みFramework
    ‣ Build時間改善
    • App, Extensionをまたぐ重複コンパイルの削減
    ✴ Target Membershipの場合各々にコピーしてコンパイル
    • 差分Buildの促進
    ✴ 「1⾏しかいじってないのに全体に…」が減らせる
    ‣ Appのサイズを⼩さくできる(起動時)
    • Dynamic Framework
    ‣ 名前空間
    • 依存関係・レイヤーを嫌でも意識、例えばAPI Clientで切る
    Embedded Framework (iOS8)
    7

    View Slide

  8. 電⼦版の導⼊の経緯
    8
    RichNotification実装しよう!
    Ref. Human Interface Guidelines

    View Slide

  9. 電⼦版の導⼊の経緯
    9
    RichNotification実装しよう!
    共有Moduleが多い…
    Membership全部に
    貼るの⾯倒くさい!!

    View Slide

  10. 電⼦版の導⼊の経緯
    10
    RichNotification実装しよう!
    共有Moduleが多い…
    未来のExtensionの数だけ

    コンパイルが遅くなる…
    Extension毎にコピー
    重複コンパイルされる

    View Slide

  11. 電⼦版の導⼊の経緯
    11
    RichNotification実装しよう!
    共有Moduleが多い…
    未来のExtensionの数だけ

    コンパイルが遅くなる…
    今のうちにFrameworkに!!

    View Slide

  12. 導⼊

    View Slide

  13. ‣ Emb に依存するLibrary/Framework
    ‣ 移⾏するModuleの設計
    ‣ 躓きやすいところ
    導⼊に向けて確認すべき項⽬
    13

    View Slide

  14. ‣ FrameworkはBridging-Headerが使えない
    • Clang Modulesを利⽤してモジュール化
    • Headerをバイナリ化するためコンパイル時間の短縮にも
    C LibraryをModule Mapでモジュール化
    14
    ※ CommonCryptoはXcode10から標準Moduleに
    #import
    #import
    shim.h
    module CommonCrypto [system] {
    header "shim.h"
    export *
    }
    module.modulemap
    CommonCrypto Module
    import CommonCrypto
    Swift
    1. ModuleMapに読み込むHeaderを記述
    2. Header Search Pathを指定
    3. Swiftファイル上でImport可能になる

    View Slide

  15. ‣ Emb FrameworkはApp専⽤APIを持てない
    • Extensionが使えないAPIはダメ(リジェクト)
    ✴ Ex.) UIApplication.shared
    • Require Only App-Extension-Safe API: YES
    ↑でBuildしたFrameworkしか利⽤できない
    ✴ してないものをLinkするとwarning
    ๏ linking against dylib not safe for use in application
    extensions
    ✴ 後述しますが、もちろん⾃前のコードに対しても対象
    Dynamic Framework Link時の注意点
    15

    View Slide

  16. ‣ EmbeddedFrameworkで使えるよう改善
    • Bridging-Headerで読んでいたものをModuleMapに
    • OSSにSafe APIフラグのPR
    • Carthage化(Membershipの重複改善)
    • どうしようもなかったらUnsafeなAPIをforkして削除
    PR投げたりCarthage化したりコード消したり…
    16

    View Slide

  17. ‣ 設計構造の⾒直し
    • 移⾏する前に設計が悪い箇所は直しておく
    ✴ Ex. UIViewControllerの型を⾒て分岐する箇所を取り除く
    ✴ Ex. App限定のAPIをApp側に持たせる(先述)
    ‣ Framework化
    1. Modulesの移⾏、Framework単体でBuild Succeed
    2. 外部(AppやExtension)から参照したいモジュールに

    アクセス修飾⼦を付加(public / open class)
    3. AppやExtensionから参照する箇所にimportを付加
    • statement毎にError出るのでものすごいエラー数になります
    Module群を移⾏
    17

    View Slide

  18. ‣ 直感的じゃないError
    • 何かが抜けて明⽰的に指定する必要性が⽣じるError
    ✴ ambiguous use of
    ✴ frameworkのimportし忘れ
    ✴ frameworkのextensionがPublicになってないとか
    • Repositoryを複製して何が参照できなくなったか

    確認できるようにしておくといい
    ‣ 他ブランチとのpbxprojの衝突がとても多い
    • (オススメMergeツールあったら教えてください)
    躓きやすいところ 1/2
    18

    View Slide

  19. ‣ Emb Frameworkで利⽤できないFramework
    • CrashlyticsはInstanceをAppにしか持つことができない
    • 【対策】
    ✴ Emb Framework上ではprotocolとして抽象的に定義

    ApplicationからEmb Frameworkに逆Injection
    ‣ protocol extensionの衝突が解決できない
    • StringをextensionしてisEmptyフィールドを定義、

    Framework同⼠で衝突すると区別することができない
    • 【対策】
    ✴ 冗⻑な名前を避ける/extensionを⼯夫して名前空間(疑似)作る
    ๏ Ex. RxSwift
    躓きやすいところ 2/2
    19

    View Slide

  20. ‣ Build回数がとにかく多い
    • Error潰してBuildしてのサイクル
    • 作業はスペックいいPCでやるべき
    ‣ スペック低いとXcodeが死ぬ
    • 適当に移⾏するとエラー700件とか平気で出る
    • Indexing Prebuilding って常にクルクルする
    • 静的解析が終わらない
    ✴ ジャンプ先が意味不明なファイルに⾶ぶ
    • 儚げに落ちる
    感覚的に⾟いところ
    20

    View Slide

  21. Build時間改善した??

    View Slide

  22. ‣ 実機iPhone7plusで3回測って平均
    ‣ 重複コンパイルしてた箇所が効いてる

    Full Buildチェック
    22
    iMacPro2017 MBP2013
    (Xcode10) Base Embed Base Embed
    Debug
    (second)
    35.87 30.03 57.93 51.03
    Release
    (second)
    125.83 98.87 213.23 172.47
    (あくまでゆるふわな実測値です)

    View Slide

  23. ‣ 差分Buildが効率的に起きててサクサク!!
    差分Buildチェック
    23
    iMacPro2017 MBP2013
    (Xcode10) FullBuild 差分Build FullBuild 差分Build
    Debug
    (second)
    35.87
    (30.03)
    19.0
    57.93
    (51.03)
    39.3
    (あくまでゆるふわな実測値です)

    View Slide

  24. ‣ 従来の2分の1以下にBuild時間が短縮
    • 僕が闘った 数秒は〜〜〜(完全にインパクト⾷われる)
    ✴ 重複・差分コンパイルの恩恵はちゃんと効いてます
    (ところで) Xcode10のBuildが凄い
    24
    iMacPro
    Xcode9 Xcode10
    Debug
    (seconds)
    81.94 30.03
    今こそEmbeddedFrameworkに⼿をつけるチャンス!!

    View Slide

  25. まとめ

    View Slide

  26. ‣ Build時間改善に役⽴つ
    • 差分Buildの促進
    • 重複コンパイルの除去
    • TargetMembership貼らなくていい
    • Appのサイズを⼩さくできる
    ✴ Dynamic Link過多に対するAppの⽴ち上がりの遅延は要確認
    • レイヤーを意識した設計にも役⽴てる
    ‣ 移⾏するぞ!!
    1. 作業時はスペックが⾼いPCでやるべき
    ‣ Build回数が通常より明らかに増えるため
    2. 依存するLibrary / Frameworkの精査
    ‣ 個⼈的にはここで苦労する⼿戻りが多かった
    3. レイヤーの切り分け・設計構造の⾒直し
    4. 移⾏ -> ひたすらErrorをつぶす
    Embedded Frameworkのススメ
    26

    View Slide