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

ラクマでのSwiftUI導入方針とTips / Rakuma SwiftUI Introduction Policy and Tips

darquro
February 16, 2022

ラクマでのSwiftUI導入方針とTips / Rakuma SwiftUI Introduction Policy and Tips

『ラクマ x STORES LTイベント ~ iOS開発の裏側 ~』での登壇資料
https://hey.connpass.com/event/236189/

darquro

February 16, 2022
Tweet

More Decks by darquro

Other Decks in Programming

Transcript

  1. ラクマでのSwiftUI導⼊⽅針とTips
    @darquro
    Rakuten Group, Inc.

    View full-size slide

  2. 2
    About Me
    @darquro
    ラクマ
    Mobile Application Development Group Manager
    / iOS Engineer

    View full-size slide

  3. 3
    Table of Contents
    • ラクマでのSwiftUI導⼊⽅針
    • SwiftUIでハマったこと
    • SwiftUI Tips
    Target
    既存のUIKitベースのアプリに
    これからSwiftUI導⼊していく⼈向け。
    ※普段からSwiftUIで開発している⼈には物⾜りないかも 🙇

    View full-size slide

  4. 4
    🗼
    ラクマでの
    SwiftUI導⼊⽅針

    View full-size slide

  5. 5
    SwiftUI導⼊
    • 2021/2〜徐々に導⼊
    • 画⾯全体もあれば、
    ⼀部コンポーネントのみなど
    • 追加読み込み(ページング)が
    不要(LazyVStackではなくListで
    済む)
    • 複雑な状態管理が不要
    という簡単な画⾯から移⾏
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  6. 6
    Architecture
    ViewController Presenter UseCase
    APIClients
    DataStores
    Repositories
    SwiftUI View ViewModel UseCase Use APIClient directory
    Use Repository
    Application Lifecycle Update
    UIKit(MVP)
    SwiftUI(MVVM)
    Presentation Layer
    Domain Layer
    Entities
    System
    User
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  7. 7
    ViewModel Protocol
    ViewModel Protocolとしてトレタさんのブログを参考に
    させていただきました 🙏
    https://tech.toreta.in/entry/2019/12/24/104612
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  8. 8
    ViewModel Protocol
    MVVMアーキテクチャは、
    単⽅向Bindingと双⽅向Binding
    の概念があるが、
    SwiftUI+Combine標準APIでは制約はない。
    Binding⽅向の制約を設けることで、コード
    の⾒通しを良くする。
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  9. 9
    ViewModel
    View
    ViewModelObject.input
    • View Lifecycleによる状態更新
    • User Actionによる状態更新
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  10. 10
    ViewModel
    View
    ViewModelObject.binding
    • ViewとViewModel双⽅のデータ更新
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  11. 11
    ViewModel
    View
    ViewModelObject.output
    • Fetchされたデータによる画⾯更新
    • Status変更による画⾯更新
    🗼ラクマでのSwiftUI導⼊⽅針

    View full-size slide

  12. 12
    💣
    SwiftUIで
    ハマったところ

    View full-size slide

  13. 13
    iOS13/iPadOS13のサポートは切ろう😇
    • TextFieldのキーボード⼊⼒まわりの挙動がおかしい
    • 謎クラッシュ
    • 標準コンポーネントが⾜りない
    • Combineのqueueを跨いぐと処理がおかしい
    などなどiOS13でSwiftUIを使うのは危険
    💣SwiftUIでハマったところ

    View full-size slide

  14. 14
    Previewがエラーになって時間ばかり取られる 🤯
    Device modelを
    定義しておくと便利👍📱
    おかしいな…なんか変だなぁ…と感じたら、
    • エディタを全部閉じる
    • Xcode再起動
    • Clean Build
    • Emulatorの起ち上げ直し
    • DerivedData削除
    最後は諦めてEmulatorで確認
    💣SwiftUIでハマったところ
    ちなみに…

    View full-size slide

  15. 15
    if statementを多⽤しない⚠
    Xcodeのcode completionがぶっ壊れて
    まともにコードが書けなくなる 🥺
    💣SwiftUIでハマったところ
    ViewModelでstateのような
    enumで条件分岐しようとすると…

    View full-size slide

  16. 16
    if #available() をViewModifierで使⽤しない💥
    Exception Type: EXC_BAD_ACCESS (SIGSEGV)
    Thread 0 name: Dispatch queue: com.apple.main-thread
    Thread 0 Crashed:
    8 SwiftUI 0x00000001a07f2160 partial apply for closure
    #1 in ModifierBodyAccessor.updateBody+ 6332768 (of:changed:) + 28
    9 SwiftUI 0x00000001a0814364 closure
    #1 in BodyAccessor.setBody+ 6472548 (_:) + 44
    10 SwiftUI 0x00000001a07f1a64
    ModifierBodyAccessor.updateBody+ 6330980 (of:changed:) + 1440
    11 SwiftUI 0x00000001a08144a8
    StaticBody.updateValue+ 6472872 () + 208
    12 SwiftUI 0x00000001a0517764
    partial apply for implicit closure #2 in implicit closure
    #1 in closure #1 in closure #1 in Attribute.init+ 3340132 (_:) + 28
    Xcode13.2 で謎クラッシュが発⽣する。しかもDebugビルドでは発⽣せず、Releaseビルドのみ起こる。
    @available()でView単位の出し分けにすることで回避
    https://developer.apple.com/forums/thread/697070
    💣SwiftUIでハマったところ

    View full-size slide

  17. 17
    🎩 🪄
    SwiftUI Tips

    View full-size slide

  18. 18
    ViewDidLoadModifier⚡
    標準だとonAppearしかないので、deta fetch系処理を⼊れてしまうと画⾯⾏き来する度にリクエストが⾛る。
    ViewDidLoadModifierを作ることで、画⾯表⽰の初回のみ呼ばれるイベントを作る。
    画⾯表⽰の初回のみ呼ばれる
    🎩 🪄SwiftUI Tips

    View full-size slide

  19. 19
    Alert Binding ⚡
    iOS15からalertのメソッドが変わった。
    ただこれらだと、状態とメッセージを別々にbindする必要が出てきて、ViewModel側が冗⻑になってくる。
    iOS14 iOS15
    🎩 🪄SwiftUI Tips

    View full-size slide

  20. 20
    Alert Binding ⚡
    iOS14にはIdentifiableをbindしてalertを出せるメソッドがあった。しかしiOS15ではなくなった。
    iOS14
    🎩 🪄SwiftUI Tips

    View full-size slide

  21. 21
    Alert Binding ⚡
    iOS14とiOS15それぞれの互換性を保ち、
    ViewModelから状態とメッセージをまとめてViewに変更を通知させたい。
    🧐
    🎩 🪄SwiftUI Tips

    View full-size slide

  22. 22
    Alert Binding ⚡
    ①ObservableObjectを使ったclassを作成。
    iOS14とiOS15それぞれの互換性を保ち、
    ViewModelから状態とメッセージをまとめてViewに変更を通知させたい。
    🎩 🪄SwiftUI Tips

    View full-size slide

  23. 23
    iOS15
    iOS14
    Alert Binding ⚡
    ②ViewModifierを作成し、iOS15以降とそれ以前の実装を書く。
    ViewModifier内でif #availableで分岐するとcrashする問題があるのでViewModifier単位で分ける。
    iOS14とiOS15それぞれの互換性を保ち、
    ViewModelから状態とメッセージをまとめてViewに変更を通知させたい。
    🎩 🪄SwiftUI Tips

    View full-size slide

  24. 24
    Alert Binding ⚡
    ③Viewのextensionを⽤意。
    iOS14とiOS15それぞれの互換性を保ち、
    ViewModelから状態とメッセージをまとめてViewに変更を通知させたい。
    🎩 🪄SwiftUI Tips

    View full-size slide

  25. 25
    ViewModel
    View
    Alert Binding ⚡
    ViewModelからメッセージ送るだけ
    実装が完結になる
    iOS14とiOS15それぞれの互換性を保ち、
    ViewModelから状態とメッセージをまとめてViewに変更を通知させたい。
    🎩 🪄SwiftUI Tips

    View full-size slide

  26. 26
    Viewodel
    Alert Binding ⚡ iOS14とiOS15それぞれの互換性を保ち、
    ViewModelから状態とメッセージをまとめてViewに変更を通知させたい。
    ④同じ要領で、.destructiveボタンと.cancelボタンの確認アラートも作成しておくと汎⽤的に使える。
    🎩 🪄SwiftUI Tips

    View full-size slide

  27. 27
    さいごに

    View full-size slide

  28. 28
    ⾊々⼤変だけど、

    View full-size slide

  29. 29
    やっていくしかないですね💪

    View full-size slide

  30. Thank you 🥳

    View full-size slide