概要
- 2025年のiPhoneでは、自分の音楽ファイル再生が困難であり、Appleの有料サービスや制限を回避する必要がある現状を説明。
- その課題を解決するため、独自の音楽プレーヤーアプリをゼロから開発した経緯を紹介。
- iCloud対応、全文検索、ローカル優先設計など、主要な技術的特徴を解説。
- React NativeからSwiftUIへの技術選択の流れと理由を詳述。
- SQLiteを用いた全文検索やiOSファイル管理の実装ポイントを整理。
iPhoneで自分の音楽を再生する困難さと独自プレーヤー開発
サブスクリプション依存とAppleの制限
- iPhoneで 自分の音楽ファイル再生 は、Apple MusicやiCloudの 有料サービス を利用しないと実現が難しい現状を確認。
- Apple Music解約後は iCloud Music Libraryの同期機能 も利用不可となり、iTunes Match(年額$24.99)で部分的に復活するが、 オリジナルファイル管理や柔軟性 に課題が残ることを認識。
- サブスクリプション型の第三者アプリも多く、 所有ファイル再生という単純なニーズ に対して不満を感じるユーザーが多いことを確認。
公式・サードパーティアプリの現状
- AppleのFilesアプリでは 音楽再生機能が限定的 で、プレイリスト管理やメタデータ並び替え、キュー管理などが不十分であることを確認。
- サードパーティ製アプリ(例:Doppler)は 単体課金モデル も存在するが、iCloudからの大量インポートや全文検索機能が弱く、 理想的なUXに到達していない ことを確認。
技術選択と開発プロセス
React NativeからSwiftUIへの移行
- 最初は React Native/Expo で開発を開始し、Web開発経験を活かそうとしたが、 iCloudディレクトリの深い階層探索やファイルアクセス制限 で多くの問題に直面。
- expo-filesystem等のライブラリは 大規模なフォルダの再帰処理に弱く、アプリクラッシュが発生しやすい状況を確認。
- iOSのサンドボックス制約により、 外部フォルダへの安定アクセスが困難 であることを実感。
- SwiftUI へ切り替え、宣言的UIと async/await・Swift Actors によるデータ同期・並列処理のしやすさを評価。
- ViewModel分離により LLM(OpenAI o1, DeepSeek等)によるUIコード生成 の効率化も実現。
- AppleネイティブAPI活用で iCloudファイルアクセスや権限管理 が容易になったことを確認。
アプリ構成とデータモデル
- SQLite を用いた永続データストアを選択し、スキーマ制御や全文検索(FTS5)を重視。
- CoreDataは 柔軟なクエリや全文検索 が難しいため採用せず。
- アプリは 3画面構成 で以下の機能を実装。
- ライブラリインポート画面:iCloudフォルダ選択・スキャン・DB登録を実行。
- ライブラリ管理画面:追加済み楽曲のプレイリスト・管理・整理を実現。
- プレーヤー画面: キュー管理(リピート・シャッフル)や再生操作 を実装。
- ユーザーフロー例:
- 初回起動時はSyncタブで「Add iCloud Source」ボタン表示→フォルダ選択→インデックス化→Libraryタブへ遷移→曲選択でミニプレーヤー起動→必要に応じてSyncで追加フォルダインポート可能。
バックエンド的なロジックレイヤー設計
- サーバアプリ的な レイヤードアーキテクチャ を採用し、UI/ViewModel層とドメインロジック層を明確に分離。
- SQLiteが最下層で生データ・FTSインデックスを保持。
- Repository層が非同期APIを提供し、その上にSwift Actorによる ビジネスロジック(インポート・検索・キュー管理) を実装。
- ViewModelはActorからデータを受け取りUI用Structへ変換、SwiftUIビューはそれを描画するのみとすることで 疎結合設計 を実現。
SQLiteによる全文検索実装
FTS5テーブル設計
- iOS 11以降は SQLite FTS5拡張が標準搭載 されており、サードパーティ依存なしで 高速なファジー検索 を実現。
- SQLite.swiftライブラリで通常クエリ、FTSは生SQLで実装。
- FTS5テーブルは2種用意:
- 楽曲インデックス用(artist, title, album, albumArtist列)
- フォルダインポート用パスインデックス(fullPath, fileName列)
- テーブル例:
CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5( songId UNINDEXED, artist, title, album, albumArtist, tokenize='unicode61' );- unicode61トークナイザーで多言語対応。
- 追加・更新は トランザクションで安全に処理 し、インデックスの不整合を防止。
ファジー検索とランキング
- ユーザー入力に自動でワイルドカードを付与し、 部分一致検索 を高速化。
- SQLiteのbm25ランキングを利用し、 関連度の高い結果を上位表示 することを実現。
- 例:
SELECT s.* FROM songs s JOIN songs_fts fts ON s.id = fts.songId WHERE songs_fts MATCH ? ORDER BY bm25(songs_fts) LIMIT ? OFFSET ?;
iOSファイル管理とブックマーク運用
- iOSでは セキュリティスコープ付きブックマーク がmacOSのみ対応で、iOSでは通常のブックマークのみ利用可能。
- ブックマークの有効期限切れや権限リセットに備え、 ファイルをアプリ内サンドボックスへバックグラウンドコピー することで、 再生時のパス不整合リスクを回避 することを重視。
このように、 Appleの制約や既存アプリの限界 に対して、自作プレーヤーを開発し、 全文検索・ローカル優先・iCloud連携 を実現した技術的アプローチと設計思想を体系的に整理した。