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

止められない医療アプリ、そっと Swift 6 へ

Avatar for MEDLEY, INC. MEDLEY, INC.
September 25, 2025

止められない医療アプリ、そっと Swift 6 へ

2025年9月21日(日)に開催のiOSDC Japan 2025の登壇資料です。
イベントURL:https://iosdc.jp/2025/
発表者情報:医療プラットフォーム本部 エンジニア 吉田将吾

Avatar for MEDLEY, INC.

MEDLEY, INC.

September 25, 2025
Tweet

More Decks by MEDLEY, INC.

Other Decks in Programming

Transcript

  1. ©/0/1 MEDLEY, INC. n 総合医療アプリ「CLINICS」 様々な機能を持つ総合医療アプリ • 病院‧薬局予約 • オンライン診療‧服薬指導

    • お薬⼿帳 • 病気‧お薬事典 今秋にブランドリニューアルを控える (ó) data.ai調べ オンライン診療アプリ国内総ダウンロード数 App Store/Google Play 合算 2023年4⽉時点
  2. ©/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 が選択される
  3. ©/0/1 MEDLEY, INC. Ô Swift のコンパイラと⾔語モード • Xcode /≤ には

    Swift ≤ のコンパイラが同梱されている • Swift ≤ のコンパイラではいくつかの⾔語モードを選択できる • Swift ≤、Swift 1、Swift n • Xcode で Swift Language Version を変更すると⾔語モードが変わる • ⾔語モードはモジュール単位で選択可能 Swift 1 ⾔語モード Swift ≤ ⾔語モード Swift 6 コンパイラ 利⽤中 Swift n ⾔語モード
  4. ©/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 ≤ でエラーを消すことで対応
  5. ©/0/1 MEDLEY, INC. óó なぜ Swift 6 移⾏をしたか 今対応しても 将来⾔語仕様が

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

    変わるかも データ競合起因の 不具合を減らせる いつかは対応する 必要がある 今じゃなくても いいんじゃないか 対応には 時間がかかる 何が何でも移⾏していくというよりは 本質的に品質を⾼める対応をしたい
  7. ©/0/1 MEDLEY, INC. ó< Swift 6 移⾏⽅針 • モジュール毎に移⾏する •

    UI を扱うクラスは @MainActor • UseCase、Repository、Entity は Sendable • 必要な場合は actor で定義 • NSObject から逃げられない箇所は @unchecked Sendable を使⽤ • 移⾏中は @preconcurrency import を利⽤ • ⾮対応のライブラリも⼀旦 @preconcurrency import で逃げる • 余⼒があれば Combine を Concurrency に移⾏する • ユニットテストはテスト対象のアクターに依存
  8. ©/0/1 MEDLEY, INC. ón Swift 6 移⾏の関係 アプリ安定性への貢献⼤ アプリ安定性への貢献⼩ 開発⼯数⼤

    開発⼯数⼩ Quick/Nimble → Swift Testing 移⾏ Combine → Concurrency 移⾏ @MainActor の付与 未対応ライブラリへの @preconcurrency import 付与 Sendable 化 (actor 化含む)
  9. ©/0/1 MEDLEY, INC. ó1 対応順序 App Feature Core Domain UI

    Feature Feature Feature ó1 モジュール構成 • CLINICSアプリはSPMマルチモ ジュールで構成 • モジュール数 : 90 • 外側のモジュールから移⾏ • Feature モジュールなど • 簡単に対応できる場合は内側の モジュールでも移⾏
  10. ©/0/1 MEDLEY, INC. ó≤ SPM マルチモジュールでの段階的 Swift 6 移⾏ •

    全体としては Swift 1 ⾔語モード を使⽤ • Feature モジュールの中でも切り 分けてモジュール単位で移⾏ App Feature Core Domain UI Feature Feature Feature Swift å ⾔語モード Swift 6 ⾔語モード ó≤ モジュール構成
  11. ©/0/1 MEDLEY, INC. ó” Package.swift での記述 • 最初に全モジュール に .swiftLanguageMode(.v1)

    を付与 • モジュール単位 で .swiftLanguageMode(.v1) を削除 • エラーを出して、エラーを解決して いく
  12. ©/0/1 MEDLEY, INC. óˇ 最終的なActor隔離状態 SwiftUI View ViewController Presenter UseCase

    Repository Entity Service Presentation Domain Data MainActor Sendable
  13. ©/0/1 MEDLEY, INC. /ó Swift 6 移⾏の関係 アプリ安定性への貢献⼤ アプリ安定性への貢献⼩ 開発⼯数⼤

    開発⼯数⼩ Quick/Nimble → Swift Testing 移⾏ Combine → Concurrency 移⾏ @MainActor の明⽰的付与 未対応ライブラリへの @preconcurrency import 付与 Sendable 化 (actor 化含む)
  14. ©/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 で呼ぶ
  15. ©/0/1 MEDLEY, INC. /< AI を活⽤した Quick/Nimble から Swift Testing

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

    を主に利⽤ • タスクによっては Devin も • ⼈によっては Cursor や Codex も • コードレビューは GitHub Copilot (Claude Code Action も利⽤可能) • BigQuery、Figma、Confluence の MCP も利⽤ • PdM やデザイナーも Claude Code を使って仕様把握や簡単な実装を実施
  17. ©/0/1 MEDLEY, INC. /1 Swift 6 環境でのランタイムエラーという⾒えないリスクの発⽣ 警告など出ないにも関わらず、Swift ≤ 環境のランタイムでクラッシュが発⽣

    ó. async let のクラッシュ • do ブロック内で async let を使うとクラッシュすることがある • Swift ≤.ó 環境で発⽣ ( Issue: swiftlang/swift #Ôó””ó ) • TaskGroup を使って回避 /. CallKit の CXCallController のクラッシュ • CXCallController に queue を設定していない場合、実⾏タスクのスレッドが 異なるとクラッシュ • queue を設定して回避
  18. ©/0/1 MEDLEY, INC. /≤ 開発環境と本番環境で Swift バージョンを切り替え、安全に浸透させる運⽤ 開発環境では Swift ≤

    を使い、QA‧本番では Swift 1 を使う移⾏期間を設けた ⽤途に応じて Swift 1 を使⽤ Swift ≤ 環境で開発 ユニットテスト ドッグフーディング 本番環境 E/E テスト Swift 1 Swift ≤
  19. ©/0/1 MEDLEY, INC. /Ô クラッシュ数の推移 • もともとクラッシュの影響を受けていないユーザ割合は 99.99% を超えていた ためクラッシュ数で⽐較

    • 徐々に減少し、Swift ≤ 移⾏が概ね完了した6⽉あたりでも明らかに減少 Swift ≤ 移⾏ほぼ完了
  20. ©/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
  21. ©/0/1 MEDLEY, INC. </ これまでの Swift 6 移⾏と Approachable Concurrency

    の⽐較 アクター隔離が未整備 ‧データ競合が起こりやすい ‧重い処理の実⾏は実装依存 MainActor 上で処理 ‧データ競合は起こりづらい ‧重い処理も MainActor で実⾏ Approachable Concurrency これまでの Swift ≤ 移⾏ @MainActor や Sendable 対応 重い処理を @concurrent などで調整 Swift ≤ 完全対応 Swift ≤ 完全対応
  22. ©/0/1 MEDLEY, INC. <n まとめ 安全なSwift 6 移⾏ • SPM

    マルチモジュールで段階的に • 警告のないランタイムクラッシュに注意 • 徐々に浸透させ対応 • Approachable Concurrency という選択も 今後の課題 • Swift ≤ 未対応のライブラリ • SwiftGen など • 乗り換えるかパッチあてるか検討中 Swift ≤.x Liquid Glass AI
  23. ©/0/1 MEDLEY, INC. <≤ We’re hiring! • iOS エンジニア積極採⽤中です •

    Android エンジニア、Flutter エンジニアも募集しています https://www.medley.jp/jobs/ https://developer.medley.jp/ Developer Portal 募集の⼀覧