Firebase Data Connect client SDKs let you call your server-side queries and mutations directly from a Firebase app. You generate a custom client SDK in parallel as you design the schemas, queries and mutations you deploy to your Data Connect service. Then, you integrate methods from this SDK into your client logic.
As we've mentioned elsewhere, it's important to note that Data Connect queries and mutations are not submitted by client code and executed on the server. Instead, when deployed, Data Connect operations are stored on the server like Cloud Functions. This means you need to deploy corresponding client-side changes to avoid breaking existing users (for example, on older app versions).
That's why Data Connect provides you with a developer environment and tooling that lets you prototype your server-deployed schemas, queries and mutations. It also generates client-side SDKs automatically, while you prototype.
When you've iterated updates to your service and client apps, both server- and client-side updates are ready to deploy.
Generate your Swift SDK
As with most Firebase projects, work on your Firebase Data Connect client code takes place in a local project directory. Both the Data Connect VS Code extension and the Firebase CLI are important local tools for generating and managing client code.
SDK generation options are keyed to several entries in the dataconnect.yaml
file generated when you initialized your project.
Initialize SDK generation
In yourconnector.yaml
, add your outputDir
, package
and (for the web SDK)
packageJsonDir
.
connectorId: "movies"
generate:
swiftSdk:
outputDir: "../movies-generated"
package: "Movies"
outputDir
specifies where the generated SDK should output to. If not specified, the connector folder is used as the default output directory.
package
specifies the name of the package that will be generated. The generator
will create a folder with the name of the package, containing Package.swift
and generated code.
observablePublisher
(optional) specifies the Observable publisher to use in
query refs. Possible values are observableMacro
(iOS 17+) and
observableObject
(pre - iOS 17). The default value, if none is specified, is
observableMacro
.
Update SDKs while prototyping
If you're prototyping interactively with the Data Connect VS Code extension
and its Data Connect emulator, SDK source files are automatically
generated and updated while you modify .gql
files defining schemas, queries
and mutations. This can be a useful feature in hot (re)loading workflows.
.gql
updates and also have SDK
sources automatically updated.
Alternatively, you can use the CLI to regenerate SDKs whenever .gql files are changed:
firebase dataconnect:sdk:generate --watch
Generate SDKs for integration and for production releases
In some scenarios, such as preparing project sources to submit for CI tests, you can call the Firebase CLI for a batch update.
In these cases, use firebase dataconnect:sdk:generate
.
Set up client code
To set up your client code to use Data Connect and your generated SDK, first follow the standard Firebase setup instructions.
Then, open your app workspace using Xcode.
In the top navigation bar, select File > Add Package Dependencies > Add
Local, and choose the folder containing the generated
Package.swift
source file.
Initialize the Data Connect iOS SDK
Initialize your Data Connect instance using the information you used to set up Data Connect (all available in the Firebase console Data Connect tab).
Getting a connector instance
The code for your connector will be generated by the
Data Connect emulator. If your connector name is movies
and the
package is movies
, as specified in connector.yaml
, then
retrieve the connector object by calling:
let connector = DataConnect.moviesConnector
Running Queries and Mutations
With the connector object, you can run queries and mutations as defined in the GraphQL source code. Suppose your connector has these operations defined:
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
}
}
You can then create a movie as follows:
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)")
To retrieve a movie, you will use a query reference. All query refs are
Observable publishers. Depending on the configured publisher (see connector.yaml)
,
they either support the @Observable
macro (iOS 17+) or implement the
ObservableObject
protocol. The default, if none is specified, is the
@Observable
macro supported on iOS 17+.
In a SwiftUI view, you can bind the query results using the published data
variable of the query ref and call the query's execute()
method to update
the data. The data
variable will match the shape of data that was defined
in your GQL query definition.
All retrieved results comply with the Decodable
protocol. If you included
the object's primary key in your GQL fetch, the objects are also Identifiable
,
allowing you to use them in iterators.
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()
}
}
Queries also support one-shot execution.
let resultData = try await DataConnect.moviesConnector.listMoviesByGenreQuery.execute(genre: "Sci-Fi")
Prototype and test your iOS application
Instrument clients to use a local emulator
You can use the Data Connect emulator, whether from the Data Connect VS Code extension or from the CLI.
Instrumenting the app to connect to the emulator is the same for both scenarios.
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
Data types in Data Connect SDKs
The Data Connect server represents common and custom GraphQL data types. These are represented in the SDK as follows.
Data Connect Type | Swift |
---|---|
String | String |
Int | Int |
Float | Double |
Boolean | Bool |
UUID | UUID |
Date | FirebaseDataConnect.LocalDate |
Timestamp | FirebaseCore.Timestamp |
Int64 | Int64 |
Any | FirebaseDataConnect.AnyValue |