🚌

ばすみる – 名古屋市営バス時刻表アプリの技術紹介

に公開

⚠️ 注意: このアプリは名古屋市営バスの公式アプリではありません。
個人開発による非公式アプリです。時刻表データの正確性や運行状況については、必ず公式情報をご確認ください。

個人開発で「ばすみる」というiOSアプリを作っています。名古屋市営バスの時刻表と接近情報をまとめて確認できる非公式アプリです。
この記事では、アプリの仕組みや GTFS-JP を使ったデータ処理、そして開発に活用した Claude Code について紹介します。
個々の詳細はまた時間のある時に別途記事にしていきたいです!


アプリ紹介

BusNow は、名古屋市営バス専用の時刻表アプリです。停留所を選ぶと、現在時刻や曜日に応じた時刻表を自動表示し、次に到着する便をハイライトしてくれます。
接近情報もアプリ内で確認できるので、乗り遅れ防止に役立ちます。

リポジトリ

スクリーンショット


アーキテクチャ

ばすみる は MVVM + Service Layer アーキテクチャを採用しています。

  • UI: SwiftUI
  • ViewModel: 停留所選択や時刻表表示の状態管理
  • Service Layer: Supabase 経由でGTFSデータを取得
  • Database: Supabase (PostgreSQL)

UIとデータ取得ロジックを分離することで、テスト容易性と保守性を高めています。


データ基盤 – GTFS-JP

BusNow の心臓部は GTFS-JP (General Transit Feed Specification - Japan) です。
GTFS は公共交通データの国際標準フォーマットで、停留所・路線・便・時刻表などをCSVで記述します。GTFS-JP は日本向け拡張仕様で、祝日や特別運行日も考慮できます。

利用している主なテーブル:

  • stops: 停留所情報
  • routes: 路線情報
  • trips: 便の運行単位
  • stop_times: 各停留所の到着・出発時刻
  • calendar: 平日・土日祝などサービス日情報
  • calendar_dates: 祝日や特別ダイヤ対応

これらのデータを Supabase にホストし、匿名アクセス可能な REST API と RPC 関数で取得しています。

サンプルコード

private func fetchBusSchedules() async {
    isLoading = true
    errorMessage = nil
    
    do {
        let schedules = try await supabaseService.getBusSchedules(
            routeId: "\(currentStationPair.departureStation)_\(currentStationPair.arrivalStation)",
            direction: selectedDirection.rawValue,
            date: targetDate
        )
        busSchedules = schedules
        updateServiceTypeFromScheduleData() // 取得データに基づいてサービスタイプを更新
        updateNextBusIndex() // 次のバスのインデックスを更新
    } catch {
        errorMessage = "時刻表の取得に失敗しました: \(error.localizedDescription)"
    }
    
    isLoading = false
}

スマート機能

  • 日付判定: 平日か土日祝かを自動判定
  • 時刻表フィルタリング: 現在時刻以降の便のみ抽出
  • スマートフォーカス: 最も近い便を自動ハイライト
  • 残り時間計算: 次のバスまでのカウントダウン表示

これらにより、アプリを開くだけで「次に来るバス」がすぐ分かります。


開発体験 – Claude Code 活用

開発過程では Claude Code を積極的に活用しました。

  • Supabase RPC や RLS 設定のSQL生成
  • SwiftUI のビュー分割やMVVMのリファクタリング提案
  • エラー原因の解析と修正案の作成
  • ユニットテストのひな形生成

サンプルプロンプトと出力

開発者

予定表画面の改善を実施します。画面内に「平日」「土日祝」ボタンがあります。ボタンを押す時の処理を追加します。本日が平日の場合、平日ボタンを押すと時の処理はそのままです。土日祝ボタンを押すと日付を加算して土曜日の日付で検索します。本日が土日祝の場合、平日ボタンを押すと日付を加算して平日の日付で検索します。

ClaudeCodeの回答

予定表画面の平日・土日祝ボタンの処理改善について理解しました。現在のコードベースを調査して、実装計画を立てます。

Searching for pattern: `**/*.swift`
(ファイル検索色々している)

現在のコードベースを調査しました。平日・土日祝ボタンの処理改善について、以下の実装計画を提案します:

Using tool: ExitPlanMode
{
  "plan": "## 平日・土日祝ボタン処理改善計画\n\n### 実装内容\n\n1. **BusScheduleViewModel.swift の修正** (BusScheduleViewModel.swift:85-88)\n   - `selectServiceType` メソッドを修正\n   - 現在の日付の種類(平日/土日祝)を判定する関数を追加\n   - 選択されたサービスタイプと現在の日付に基づいて適切な日付を計算\n   - 計算された日付を使用してスケジュールを読み込み\n\n2. **日付計算ロジックの追加**\n   - 本日が平日で土日祝ボタンを押した場合:次の土曜日の日付に変更\n   - 本日が土日祝で平日ボタンを押した場合:次の平日(月曜日)の日付に変更\n   - 同じボタンを押した場合は現在の日付のまま\n\n3. **SupabaseService.swift の修正** (SupabaseService.swift:63-84)\n   - `getBusSchedules` メソッドで渡される日付パラメータを使用\n   - 現在は `Date()` を使用しているが、ViewModelから渡される日付を使用するよう修正\n\n### 具体的な変更箇所\n\n- `BusScheduleViewModel`: 日付判定ロジックと日付計算機能を追加\n- `selectServiceType`: 選択されたサービスタイプに応じて適切な日付を計算して使用\n- `SupabaseService.getBusSchedules`: 日付パラメータの使用方法を改善\n\n### 期待される動作\n\n- 平日に土日祝ボタン押下 → 次の土曜日の時刻表を表示\n- 土日祝に平日ボタン押下 → 次の月曜日の時刻表を表示\n- 同じタイプのボタン押下 → 本日の時刻表を表示"
}

Tool Result
User has approved your plan. You can now start coding. Start with updating your todo list if applicable

Todo List
BusScheduleViewModelに日付判定と計算のロジックを追加
selectServiceTypeメソッドを修正して適切な日付を計算
SupabaseServiceのgetBusSchedulesメソッドを修正
動作確認とテスト

SupabaseServiceのgetBusSchedulesメソッドは既に修正済みであることを確認しました。date: targetDateを使用するよう変更済みです。

AI コーディングアシスタントを導入することで、設計検討から実装、テストまで一貫して効率化できました。


セキュリティと運用

  • RLS (Row Level Security) による安全なデータ公開
  • .xcconfig による機密情報の管理
  • 匿名アクセス・個人情報収集なし

まとめ

BusNow は GTFS-JP を活用した拡張性のあるバス時刻表アプリです。
Claude Code の支援により、効率的な開発と高品質な実装が可能になりました。
今後はプッシュ通知やお気に入り機能の追加を予定しています。


リポジトリや技術詳細に興味がある方はぜひ覗いてみてください!

Discussion