生成された iOS SDK を使用する

Firebase SQL Connect クライアント SDK を使用すると、Firebase アプリからサーバーサイドのクエリと ミューテーションを直接呼び出すことができます。SQL Connect サービスにデプロイするスキーマ、クエリ、ミューテーションを設計するのと 並行して、カスタム クライアント SDK を SQL Connect 生成します。次に、この SDK のメソッドをクライアント ロジックに統合します。

他の場所でも説明したように、SQL Connect クエリとミューテーションはクライアント コードによって送信され、 サーバーで実行されるわけではないことに注意してください。代わりに、デプロイされると、SQL Connect オペレーションは Cloud Functions のように サーバーに保存されます。つまり、既存のユーザー(古いアプリのバージョンなど)に影響を与えないようにするには、対応するクライアントサイドの変更をデプロイする必要があります。

そのため、SQL Connect には、サーバーにデプロイされたスキーマ、クエリ、ミューテーションのプロトタイプを作成できる開発環境と ツールが用意されています。 また、プロトタイプ作成中にクライアントサイドの SDK が自動的に生成されます。

サービスとクライアント アプリの更新を繰り返したら、サーバーサイドとクライアントサイドの両方の更新をデプロイする準備が整います。

クライアント開発ワークフローとは

スタートガイドに沿って進めた場合は、スタートガイドに沿って進めた場合は、 全体的な開発フローについて説明しました。SQL Connectこのガイドでは、スキーマから Swift SDK を生成し、クライアントのクエリとミューテーションを操作する方法について詳しく説明します。

まとめると、生成された Swift SDK をクライアント アプリで使用するには、次の前提条件の手順を行います。

  1. iOS アプリに Firebase を追加します。
  2. 生成された SDK を使用するには、Xcode で依存関係として構成します。

    Xcode の上部のナビゲーション バーで、[File] > [Add Package Dependencies] > [Add Local] を選択し、生成された Package.swift を含むフォルダを選択します。

その後の操作は次のとおりです。

  1. アプリのスキーマを開発します。
  2. SDK の生成を設定します。

  3. クライアント コードを初期化してライブラリをインポートします

  4. クエリとミューテーションの呼び出しを実装します

  5. エミュレータSQL Connect設定して使用し、 反復処理を行います。

Swift SDK を生成する

Firebase CLI を使用して、アプリに SQL Connect で生成された SDK を設定します。 init コマンドは、現在のフォルダ内のすべてのアプリを検出し、生成された SDK を自動的にインストールします。

firebase init dataconnect:sdk

プロトタイプ作成中に SDK を更新する

SQL Connect VS Code 拡張機能をインストールしている場合、生成された SDK は常に最新の状態に保たれます。

SQL Connect VS Code 拡張機能を使用しない場合は、Firebase CLI を使用して、生成された SDK を最新の状態に保つことができます。

firebase dataconnect:sdk:generate --watch

ビルド パイプラインで SDK を生成する

Firebase CLI を使用して、CI/CD ビルドプロセスで SQL Connect SDK を生成できます。

firebase dataconnect:sdk:generate

SQL Connect iOS SDK を初期化する

SQL Connect インスタンスの設定に使用した情報(Firebase コンソールの SQL Connect タブで確認可能)を使用して、SQL Connect インスタンスを初期化します。

コネクタ インスタンスを取得する

コネクタのコードは、 SQL Connect エミュレータによって生成されます。connector.yaml で指定されているように、コネクタ名が movies でパッケージが movies の場合は、次の呼び出しでコネクタ オブジェクトを取得します。

let connector = DataConnect.moviesConnector

クエリとミューテーションを実装する

コネクタ オブジェクトを使用すると、GraphQL ソースコードで定義されているクエリとミューテーションを実行できます。コネクタに次のオペレーションが定義されているとします。

mutation createMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}

query getMovieByKey($key: Movie_Key!) {
  movie(key: $key) { id title }
}

query listMoviesByGenre($genre: String!) {
  movies(where: {genre: {eq: $genre}}) {
    id
    title
  }
}

次のようにムービーを作成できます。

let mutationResult = try await connector.createMovieMutation.execute(
  title: "Empire Strikes Back",
  releaseYear: 1980,
  genre: "Sci-Fi",
  rating: 5)

print("Movie ID: \(mutationResult.data.movie_insert.id)")

ムービーを取得するには、クエリ参照を使用します。すべてのクエリ参照は Observable パブリッシャーです。構成されたパブリッシャーに応じて(connector.yaml)を参照)、@Observableマクロ(iOS 17 以降)をサポートするか、ObservableObjectプロトコルを実装します。指定しない場合のデフォルトは、iOS 17 以降でサポートされている @Observable マクロです。

SwiftUI ビューでは、クエリ参照の公開された data 変数を使用してクエリ結果をバインドし、クエリの execute() メソッドを呼び出してデータを更新できます。data 変数は、GQL クエリ定義で定義されたデータの形状と一致します。

取得した結果はすべて Decodable プロトコルに準拠しています。オブジェクトの主キーを GQL フェッチに含めた場合、オブジェクトは Identifiable でもあるため、イテレータで使用できます。

struct ListMovieView: View {
    @StateObject private var queryRef = connector.listMoviesByGenreQuery.ref(genre: "Sci-Fi")
    var body: some View {
        VStack {
            Button {
                Task {
                    do {
                        try await refresh()
                    } catch {
                        print("Failed to refresh: \(error)")
                    }
                }
            } label: {
                Text("Refresh")
            }
                // use the query results in a view
            ForEach(queryRef.data?.movies ?? [], id: \.self.id) { movie in
                    Text(movie.title)
                }
            }
    }
    @MainActor
    func refresh() async throws {
        _ = try await queryRef.execute()
    }
}

クエリは 1 回限りの実行もサポートしています。

let resultData = try await DataConnect.moviesConnector.listMoviesByGenreQuery.execute(genre: "Sci-Fi")

列挙フィールドの変更を処理する

アプリのスキーマには、列挙を含めることができ、 これはGraphQL クエリでアクセスできます。

アプリのデザインが変更されると、サポートされる新しい列挙値を追加できます。たとえば、アプリケーションのライフサイクルの後半で、AspectRatio 列挙に FULLSCREEN 値を追加するとします。

SQL Connect ワークフローでは、ローカル開発ツールを使用して クエリと SDK を更新できます。

ただし、クライアントの更新バージョンをリリースする前に、デプロイ済みの古いクライアントが破損する可能性があります。

復元力のある実装例

生成された列挙型には _UNKNOWN 値が含まれており、Swift では網羅的な switch ステートメントが強制されるため、生成された SDK では不明な値の処理が強制されます。

do {
    let result = try await DataConnect.moviesConnector.listMovies.execute()
    if let data = result.data {
        for movie in data.movies {
            switch movie.aspectratio {
                case .ACADEMY: print("academy")
                case .WIDESCREEN: print("widescreen")
                case .ANAMORPHIC: print("anamorphic")
                case ._UNKNOWN(let unknownAspect): print(unknownAspect)
            }
        }
    }
} catch {
    // handle error
}

クライアントサイド キャッシュを有効にする

SQL Connect には、クライアントサイド キャッシュ機能(省略可)があります。この機能を有効にするには、connector.yaml ファイルを編集します。この機能を有効にすると、生成されたクライアント SDK はクエリ レスポンスをローカルにキャッシュします。これにより、アプリが送信するデータベース リクエストの数を減らし、ネットワークが利用できない場合でもアプリのデータベース依存部分が動作するようにできます。

クライアントサイド キャッシュを有効にするには、コネクタ構成にクライアント キャッシュ構成を追加します。

generate:
  swiftSdk:
    outputDir: "../ios"
    package: "FirebaseDataConnectGenerated"
    clientCache:
      maxAge: 5s
      storage: persistent

この構成には 2 つのパラメータがあり、どちらも省略可能です。

  • maxAge: キャッシュされたレスポンスがクライアント SDK で新しい値がフェッチされるまでの最大経過時間。例: "0"、"30s"、"1h30m"。

    maxAge のデフォルト値は 0 です。つまり、レスポンスはキャッシュされますが、クライアント SDK は常に新しい値をフェッチします。キャッシュされた値は、execute()CACHE_ONLY が指定されている場合にのみ使用されます。

  • storage: クライアント SDK は、レスポンスを persistent ストレージまたは memory にキャッシュするように構成できます。persistent ストレージにキャッシュされた結果は、アプリの再起動後も保持されます。iOS SDK のデフォルトは persistent です。

コネクタのキャッシュ構成を更新したら、クライアント SDK を再生成してアプリを再ビルドします。これにより、execute() はキャッシュ レスポンスをキャッシュし、構成したポリシーに従ってキャッシュされた値を使用します。通常、この処理は自動的に行われ、追加の手順は必要ありませんが、次の点に注意してください。

  • execute() のデフォルトの動作は上記のとおりです。クエリの結果がキャッシュされ、キャッシュされた値が maxAge より古くない場合は、キャッシュされた値を使用します。このデフォルトの動作は PREFER_CACHE ポリシーと呼ばれます。

    また、execute() の個々の呼び出しに対して、キャッシュされた値のみを処理する(CACHE_ONLY)か、サーバーから新しい値を無条件にフェッチする(SERVER_ONLY)かを指定することもできます。

    try await execute(fetchPolicy: .cacheOnly)
    
    try await execute(fetchPolicy: .serverOnly)
    

    iOS アプリのプロトタイプを作成してテストする

    ローカル エミュレータを使用するようにクライアントをインストルメントする

    SQL Connect エミュレータは、 SQL Connect VS Code 拡張機能または CLI から使用できます。

    エミュレータに接続するようにアプリをインストルメントする方法は、どちらのシナリオでも同じです。

    let connector = DataConnect.moviesConnector
    // Connect to the emulator on "127.0.0.1:9399"
    connector.useEmulator()
    
    // (alternatively) if you're running your emulator on non-default port:
    connector.useEmulator(port: 9999)
    
    // Make calls from your app
    

    SQL Connect SDK のデータ型

    SQL Connect サーバーは、一般的な GraphQL データ型とカスタム GraphQL データ型を表します。これらは SDK で次のように表されます。

    SQL Connect の型 Swift
    文字列 文字列
    Int Int
    浮動小数点数 Double
    ブール値 Bool
    UUID UUID
    日付 FirebaseDataConnect.LocalDate
    タイムスタンプ FirebaseCore.Timestamp
    Int64 Int64
    すべて FirebaseDataConnect.AnyValue