Cómo usar los SDKs de iOS generados

Los SDK de cliente de Firebase SQL Connect te permiten llamar a tus consultas y mutaciones del servidor directamente desde una app de Firebase. Generas un SDK de cliente personalizado en paralelo mientras diseñas los esquemas, las consultas y las mutaciones que implementas en tu SQL Connect servicio. Luego, integras métodos de este SDK en tu lógica de cliente.

Como mencionamos en otro lugar, es importante tener en cuenta que el código de cliente no envía las SQL Connect consultas y mutaciones, y que estas no se ejecutan en el servidor. En cambio, cuando se implementan, las operaciones de SQL Connect se almacenan en el servidor como Cloud Functions. Esto significa que debes implementar los cambios correspondientes del cliente para evitar interrumpir a los usuarios existentes (por ejemplo, en versiones anteriores de la app).

Por eso, SQL Connect te proporciona un entorno de desarrollo y herramientas que te permiten crear prototipos de tus esquemas, consultas y mutaciones implementados en el servidor. También genera SDKs de cliente automáticamente mientras creas prototipos.

Cuando hayas iterado las actualizaciones de tu servicio y las apps de cliente, las actualizaciones del servidor y del cliente estarán listas para implementarse.

¿Cuál es el flujo de trabajo de desarrollo del cliente?

Si seguiste la guía de inicio, se te presentó el flujo de desarrollo general de SQL Connect. En esta guía, encontrarás información más detallada sobre la generación de SDKs de Swift a partir de tu esquema y el trabajo con consultas y mutaciones del cliente.

En resumen, para usar los SDKs de Swift generados en tus apps de cliente, debes seguir estos pasos previos:

  1. Agrega Firebase a tu app para iOS.
  2. Para usar el SDK generado, configúralo como una dependencia en Xcode.

    En la barra de navegación superior de Xcode, selecciona File > Add Package Dependencies > Add Local y elige la carpeta que contiene el archivo Package.swift generado.

Luego:

  1. Desarrolla el esquema de tu app.
  2. Configura la generación del SDK:

  3. Inicializa tu código de cliente y las bibliotecas de importación.

  4. Implementa llamadas a consultas y mutaciones.

  5. Configura y usa el emulador SQL Connect y realiza iteraciones.

Genera tu SDK de Swift

Usa el Firebase CLI para configurar los SDKs generados de SQL Connect en tus apps. El comando init debe detectar todas las apps en la carpeta actual y, luego, instalar los SDKs generados automáticamente.

firebase init dataconnect:sdk

Actualiza los SDKs mientras creas prototipos

Si tienes instalada la extensión de SQL Connect para VS Code, siempre mantendrá actualizados los SDKs generados.

Si no usas la extensión de SQL Connect para VS Code, puedes usar Firebase CLI para mantener actualizados los SDKs generados.

firebase dataconnect:sdk:generate --watch

Genera SDKs en canalizaciones de compilación

Puedes usar Firebase CLI para generar SQL Connect SDKs en procesos de compilación de CI/CD.

firebase dataconnect:sdk:generate

Inicializa el SDK de iOS SQL Connect

Inicializa tu SQL Connect instancia con la información que usaste para configurar SQL Connect (todo disponible en la Firebase console SQL Connect tab).

Obtén una instancia de conector

El emulador SQL Connect generará el código de tu conector. Si el nombre del conector es movies y el paquete es movies, como se especifica en connector.yaml, recupera el objeto del conector llamando a:

let connector = DataConnect.moviesConnector

Implementa consultas y mutaciones

Con el objeto del conector, puedes ejecutar consultas y mutaciones como se define en el código fuente de GraphQL. Supongamos que tu conector tiene definidas estas operaciones:

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
  }
}

Luego, puedes crear una película de la siguiente manera:

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)")

Para recuperar una película, usarás una referencia de consulta. Todas las referencias de consulta son publicadores observables. Según el publicador configurado (consulta connector.yaml), admiten la macro @Observable (iOS 17+) o implementan el ObservableObject protocolo. El valor predeterminado, si no se especifica ninguno, es la macro @Observable compatible con iOS 17+.

En una vista de SwiftUI, puedes vincular los resultados de la consulta con la variable data publicada de la referencia de consulta y llamar al método execute() de la consulta para actualizar los datos. La variable data coincidirá con la forma de los datos que se definieron en la definición de la consulta de GQL.

Todos los resultados recuperados cumplen con el protocolo Decodable. Si incluiste la clave principal del objeto en tu recuperación de GQL, los objetos también son Identifiable, lo que te permite usarlos en iteradores.

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()
    }
}

Las consultas también admiten la ejecución única.

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

Controla los cambios en los campos de enumeración

El esquema de una app puede contener enumeraciones, a las que pueden acceder tus consultas de GraphQL.

A medida que cambia el diseño de una app, puedes agregar nuevos valores admitidos de enum. Por ejemplo, imagina que, más adelante en el ciclo de vida de tu aplicación, decides agregar un valor FULLSCREEN a la enum AspectRatio.

En el flujo de trabajo SQL Connect, puedes usar herramientas de desarrollo locales para actualizar tus consultas y SDKs.

Sin embargo, antes de lanzar una versión actualizada de tus clientes, es posible que los clientes implementados más antiguos se interrumpan.

Ejemplo de implementación resistente

El SDK generado fuerza el control de valores desconocidos, ya que las enums generadas contienen un valor _UNKNOWN, y Swift aplica instrucciones de cambio exhaustivas.

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
}

Habilita el almacenamiento en caché del cliente

SQL Connect tiene una función opcional de almacenamiento en caché del cliente, que puedes habilitar editando el archivo connector.yaml. Cuando se habilita esta función, los SDKs de cliente generados almacenan en caché de forma local las respuestas de las consultas, lo que puede reducir la cantidad de solicitudes de base de datos que realiza tu app y permite que las partes de la app que dependen de la base de datos funcionen cuando se interrumpe la disponibilidad de la red.

Para habilitar el almacenamiento en caché del cliente, agrega una configuración de almacenamiento en caché del cliente a la configuración del conector:

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

Esta configuración tiene dos parámetros, ambos opcionales:

  • maxAge: Es la antigüedad máxima que puede tener una respuesta almacenada en caché antes de que el SDK de cliente recupere valores nuevos. Ejemplos: "0", "30s", "1h30m".

    El valor predeterminado de maxAge es 0, lo que significa que las respuestas se almacenan en caché, pero el SDK de cliente siempre recuperará valores nuevos. Los valores almacenados en caché solo se usarán cuando se especifique CACHE_ONLY en execute().

  • storage: El SDK de cliente se puede configurar para almacenar en caché las respuestas en el almacenamiento persistent o en la memory. Los resultados almacenados en caché en el almacenamiento persistent se conservarán entre los reinicios de la app. En los SDKs de iOS, el valor predeterminado es persistent.

Después de actualizar la configuración de almacenamiento en caché del conector, vuelve a generar los SDKs de cliente y vuelve a compilar tu app. Una vez que lo hagas, execute() almacenará en caché las respuestas y usará los valores almacenados en caché según la política que configuraste. Por lo general, esto sucede automáticamente, sin que tengas que realizar pasos adicionales. Sin embargo, ten en cuenta lo siguiente:

  • El comportamiento predeterminado de execute() es el que se describió anteriormente: si un resultado se almacena en caché para una consulta y el valor almacenado en caché no es más antiguo que maxAge, usa el valor almacenado en caché. Este comportamiento predeterminado se denomina política PREFER_CACHE.

    También puedes especificar invocaciones individuales de execute() para que solo entreguen valores almacenados en caché (CACHE_ONLY) o para recuperar valores nuevos del servidor de forma incondicional (SERVER_ONLY).

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

    Crea prototipos y prueba tu aplicación para iOS

    Instrumenta clientes para usar un emulador local

    Puedes usar el SQL Connect emulador, ya sea desde la extensión de SQL Connect para VS Code o desde la CLI.

    La instrumentación de la app para conectarse al emulador es la misma en ambos casos.

    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
    

    Tipos de datos en los SDKs SQL Connect

    El servidor SQL Connect representa tipos de datos de GraphQL comunes y personalizados. Estos se representan en el SDK de la siguiente manera.

    Tipo de SQL Connect Swift
    String String
    Int Int
    Float Double
    Boolean Bool
    UUID UUID
    Date FirebaseDataConnect.LocalDate
    Timestamp FirebaseCore.Timestamp
    Int64 Int64
    Any FirebaseDataConnect.AnyValue