Slide 1

Slide 1 text

⽌められない医療アプリ、そっと Swift 6 へ 株式会社メドレー 吉⽥ 将吾

Slide 2

Slide 2 text

⽯橋を叩きながら渡った Swift 6 移⾏についてお話できればと

Slide 3

Slide 3 text

©/0/1 MEDLEY, INC. < 会社紹介 メドレーは、テクノロジーを活⽤した事業やプロジェクトを通じて「納得できる医療」の実現を⽬指します (1) 2025年6⽉末時点

Slide 4

Slide 4 text

©/0/1 MEDLEY, INC. n 総合医療アプリ「CLINICS」 様々な機能を持つ総合医療アプリ • 病院‧薬局予約 • オンライン診療‧服薬指導 • お薬⼿帳 • 病気‧お薬事典 今秋にブランドリニューアルを控える (ó) data.ai調べ オンライン診療アプリ国内総ダウンロード数 App Store/Google Play 合算 2023年4⽉時点

Slide 5

Slide 5 text

©/0/1 MEDLEY, INC. 1 Swift 6 について

Slide 6

Slide 6 text

©/0/1 MEDLEY, INC. ≤ Swift 6 について • 2024年9⽉にリリース • Swift 1 は2019年3⽉リリースなので5年ぶりのメジャーバージョンアップ • 様々な機能が含まれている • Concurrency • Typed throws • Ownership • C++ interoperability • Embedded Swift • Xcode /≤.0 で新規プロジェクトを作成しても Swift 1 が選択される

Slide 7

Slide 7 text

©/0/1 MEDLEY, INC. ” Swift 6 の祝福と呪い データ競合をコンパイル時にエラーとして検出 →「稀にクラッシュする」から「事前にエラーが出る」へ 潜在的なデータ競合が多いと⼤量のエラーが出る → Swift 界隈に多くの混乱をもたらした

Slide 8

Slide 8 text

©/0/1 MEDLEY, INC. Ô Swift のコンパイラと⾔語モード • Xcode /≤ には Swift ≤ のコンパイラが同梱されている • Swift ≤ のコンパイラではいくつかの⾔語モードを選択できる • Swift ≤、Swift 1、Swift n • Xcode で Swift Language Version を変更すると⾔語モードが変わる • ⾔語モードはモジュール単位で選択可能 Swift 1 ⾔語モード Swift ≤ ⾔語モード Swift 6 コンパイラ 利⽤中 Swift n ⾔語モード

Slide 9

Slide 9 text

©/0/1 MEDLEY, INC. ˇ Swift 6 移⾏とは Swift 1 ⾔語モード Swift ≤ ⾔語モード Swift 6 コンパイラ 利⽤中 Swift n ⾔語モード • Swift の⾔語モードを 5 から 6 に上げて、コンパイルできることを Swift ≤ 移⾏ とする • Strict Concurrency Checking で Swift 1 では警告だった箇所が Swift ≤ ではエ ラーとなる • Swift 1 で警告を消すか Swift ≤ でエラーを消すことで対応

Slide 10

Slide 10 text

©/0/1 MEDLEY, INC. ó0 CLINICS アプリの Swift 6 移⾏

Slide 11

Slide 11 text

©/0/1 MEDLEY, INC. óó なぜ Swift 6 移⾏をしたか 今対応しても 将来⾔語仕様が 変わるかも データ競合起因の 不具合を減らせる いつかは対応する 必要がある 今じゃなくても いいんじゃないか 対応には 時間がかかる

Slide 12

Slide 12 text

©/0/1 MEDLEY, INC. ó/ なぜ Swift 6 移⾏をしたか 今対応しても 将来⾔語仕様が 変わるかも データ競合起因の 不具合を減らせる いつかは対応する 必要がある 今じゃなくても いいんじゃないか 対応には 時間がかかる 何が何でも移⾏していくというよりは 本質的に品質を⾼める対応をしたい

Slide 13

Slide 13 text

©/0/1 MEDLEY, INC. ó< Swift 6 移⾏⽅針 • モジュール毎に移⾏する • UI を扱うクラスは @MainActor • UseCase、Repository、Entity は Sendable • 必要な場合は actor で定義 • NSObject から逃げられない箇所は @unchecked Sendable を使⽤ • 移⾏中は @preconcurrency import を利⽤ • ⾮対応のライブラリも⼀旦 @preconcurrency import で逃げる • 余⼒があれば Combine を Concurrency に移⾏する • ユニットテストはテスト対象のアクターに依存

Slide 14

Slide 14 text

©/0/1 MEDLEY, INC. ón Swift 6 移⾏の関係 アプリ安定性への貢献⼤ アプリ安定性への貢献⼩ 開発⼯数⼤ 開発⼯数⼩ Quick/Nimble → Swift Testing 移⾏ Combine → Concurrency 移⾏ @MainActor の付与 未対応ライブラリへの @preconcurrency import 付与 Sendable 化 (actor 化含む)

Slide 15

Slide 15 text

©/0/1 MEDLEY, INC. ó1 対応順序 App Feature Core Domain UI Feature Feature Feature ó1 モジュール構成 • CLINICSアプリはSPMマルチモ ジュールで構成 • モジュール数 : 90 • 外側のモジュールから移⾏ • Feature モジュールなど • 簡単に対応できる場合は内側の モジュールでも移⾏

Slide 16

Slide 16 text

©/0/1 MEDLEY, INC. ó≤ SPM マルチモジュールでの段階的 Swift 6 移⾏ • 全体としては Swift 1 ⾔語モード を使⽤ • Feature モジュールの中でも切り 分けてモジュール単位で移⾏ App Feature Core Domain UI Feature Feature Feature Swift å ⾔語モード Swift 6 ⾔語モード ó≤ モジュール構成

Slide 17

Slide 17 text

©/0/1 MEDLEY, INC. ó” Package.swift での記述 • 最初に全モジュール に .swiftLanguageMode(.v1) を付与 • モジュール単位 で .swiftLanguageMode(.v1) を削除 • エラーを出して、エラーを解決して いく

Slide 18

Slide 18 text

©/0/1 MEDLEY, INC. óÔ CLINICS アプリのレイヤー構造 SwiftUI View ViewController Presenter UseCase Repository Entity Service Presentation Domain Data

Slide 19

Slide 19 text

©/0/1 MEDLEY, INC. óˇ 最終的なActor隔離状態 SwiftUI View ViewController Presenter UseCase Repository Entity Service Presentation Domain Data MainActor Sendable

Slide 20

Slide 20 text

©/0/1 MEDLEY, INC. /0 コード例

Slide 21

Slide 21 text

©/0/1 MEDLEY, INC. /ó Swift 6 移⾏の関係 アプリ安定性への貢献⼤ アプリ安定性への貢献⼩ 開発⼯数⼤ 開発⼯数⼩ Quick/Nimble → Swift Testing 移⾏ Combine → Concurrency 移⾏ @MainActor の明⽰的付与 未対応ライブラリへの @preconcurrency import 付与 Sendable 化 (actor 化含む)

Slide 22

Slide 22 text

©/0/1 MEDLEY, INC. // Combine から Swift Concurrency への移⾏ • 外側のモジュールから Concurrency へ移⾏ • Combine を Concurrency から呼べるコードを作成して使⽤ • 最後に OpenAPI Generator のコード⽣成を AsyncAwait に変更 • AIを積極的に利⽤ OpenAPI Generator Repository Presenter ① Combine で呼ぶ ↓ Concurrency で呼ぶ ② Combine → Concurrency ① Combine → Concurrency ③ Combine → Concurrency ② Combine で呼ぶ ↓ Concurrency で呼ぶ

Slide 23

Slide 23 text

©/0/1 MEDLEY, INC. /< AI を活⽤した Quick/Nimble から Swift Testing への移⾏ • Quick/Nimble の学習コストが課題となっていた • もともとバックエンドのエンジニアが iOS アプリ開発をしていた経緯 • AI を使って⼀気に移⾏ • 移⾏⽅法のドキュメントを作成し、それをもとに AI に変換してもらう ファイルを指定 移⾏⽅法のドキュメント Swift Testing に 変換されたコード

Slide 24

Slide 24 text

©/0/1 MEDLEY, INC. /n CLINICSアプリチームでの AI 活⽤ • Claude Code を主に利⽤ • タスクによっては Devin も • ⼈によっては Cursor や Codex も • コードレビューは GitHub Copilot (Claude Code Action も利⽤可能) • BigQuery、Figma、Confluence の MCP も利⽤ • PdM やデザイナーも Claude Code を使って仕様把握や簡単な実装を実施

Slide 25

Slide 25 text

©/0/1 MEDLEY, INC. /1 Swift 6 環境でのランタイムエラーという⾒えないリスクの発⽣ 警告など出ないにも関わらず、Swift ≤ 環境のランタイムでクラッシュが発⽣ ó. async let のクラッシュ • do ブロック内で async let を使うとクラッシュすることがある • Swift ≤.ó 環境で発⽣ ( Issue: swiftlang/swift #Ôó””ó ) • TaskGroup を使って回避 /. CallKit の CXCallController のクラッシュ • CXCallController に queue を設定していない場合、実⾏タスクのスレッドが 異なるとクラッシュ • queue を設定して回避

Slide 26

Slide 26 text

©/0/1 MEDLEY, INC. /≤ 開発環境と本番環境で Swift バージョンを切り替え、安全に浸透させる運⽤ 開発環境では Swift ≤ を使い、QA‧本番では Swift 1 を使う移⾏期間を設けた ⽤途に応じて Swift 1 を使⽤ Swift ≤ 環境で開発 ユニットテスト ドッグフーディング 本番環境 E/E テスト Swift 1 Swift ≤

Slide 27

Slide 27 text

©/0/1 MEDLEY, INC. /” Swift 6 対応の結果

Slide 28

Slide 28 text

©/0/1 MEDLEY, INC. /Ô クラッシュ数の推移 • もともとクラッシュの影響を受けていないユーザ割合は 99.99% を超えていた ためクラッシュ数で⽐較 • 徐々に減少し、Swift ≤ 移⾏が概ね完了した6⽉あたりでも明らかに減少 Swift ≤ 移⾏ほぼ完了

Slide 29

Slide 29 text

©/0/1 MEDLEY, INC. /ˇ 対応後のチームの意⾒ Swift Concurrencyにして コードの⾒通しが良くなった 不具合が減ったので やった価値があった スレッドの理解が 深まった

Slide 30

Slide 30 text

©/0/1 MEDLEY, INC. <0 余談 : Approachable Concurrencyについて

Slide 31

Slide 31 text

©/0/1 MEDLEY, INC. <ó Swift 6.Œ、Xcode Œ6 での Swift 6 対応 Approachable Concurrency • Swift ≤ を導⼊しやすくするための機能群 • Xcode /≤ の新規プロジェクトではデフォルトで On 機能群 • Default Actor Isolation • モジュール内のコードが指定したアクターで実⾏ • nonisolated か MainActor を選択 • nonisolated(nonsending) By Default • 呼び出し先が呼び出し元のアクターで実⾏ • Infer Isolated Conformances View ViewModel UseCase Repository MainActor MainActor MainActor

Slide 32

Slide 32 text

©/0/1 MEDLEY, INC.

Slide 33

Slide 33 text

©/0/1 MEDLEY, INC. << まとめ

Slide 34

Slide 34 text

©/0/1 MEDLEY, INC.

Slide 35

Slide 35 text

©/0/1 MEDLEY, INC. <≤ We’re hiring! • iOS エンジニア積極採⽤中です • Android エンジニア、Flutter エンジニアも募集しています https://www.medley.jp/jobs/ https://developer.medley.jp/ Developer Portal 募集の⼀覧