← Files FirebaseARCHIVED FILE

reference/sdk_ios.md

4.23 KB · Oct 3, 2026 · 06:21 UTC

↓ Download file

# iOS SDK

Consult this file when writing iOS application code (Swift) that interacts with
the SQL Connect backend.

### Best Practices for Agents

- **Understand Operation Storage**: SQL Connect queries and mutations are stored
  on the server like Cloud Functions. **Whenever you update operations, you must
  regenerate the SDK and redeploy services** that use it to avoid breaking
  clients.
- **Resilient Enum Handling**: The generated SDK forces handling of unknown
  values by adding an `._UNKNOWN` case. Swift enforces exhaustive switch
  statements, so you must handle this case.
- **Observable Macro**: By default, query refs support the `@Observable` macro
  (iOS 17+), making them ideal for binding to SwiftUI views. The bindable query
  results are available in the `data` variable of the query ref.
- **Handle Errors**: Use `try await` with operation execution as they are
  asynchronous and may throw errors.

### Dependencies (Package.swift or SPM)

Configure the generated SDK as a package dependency in Xcode.

### Initialization

Retrieve the generated connector instance:

```swift
import FirebaseCore
import FirebaseDataConnect

// Assuming connector name is 'movies' in connector.yaml
// The connector name is the lower camel case connectorId defined in connector.yaml suffixed with the word 'Connector'
let connector = DataConnect.moviesConnector

// For local development with emulator
// Defaults to 127.0.0.1:9399
connector.useEmulator() 
// Or specify a non-default port:
// connector.useEmulator(port: 9999)
```

### Calling Operations

#### Basic Query

```swift
let result = try await connector.listMovies.execute()
for movie in result.data.movies {
    print(movie.title)
}
```

#### Mutation

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

### Resilient Enum Handling

Handle generated enums exhaustively, including the `._UNKNOWN` case.

```swift
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("Unknown: \(unknownAspect)")
            }
        }
    }
} catch {
    // handle error
}
```

### Client-Side Caching

Enable caching in `connector.yaml` to reduce requests, support offline
scenarios, enable realtime support for queries.

```yaml
generate:
  swiftSdk:
    outputDir: "../ios"
    package: "FirebaseDataConnectGenerated"
    clientCache:
      maxAge: 5s
      storage: persistent # Default for iOS is persistent
```

Use cache policies in code:

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

### Subscriptions (Realtime)

#### SwiftUI Example

```swift
import Combine
import SwiftUI

struct ListMovieView: View {
    // QueryRef has the Observable attribute, so its properties will
    // automatically trigger updates on changes.
    private var queryRef = connector.listMoviesByGenreQuery.ref(genre: "Sci-Fi")

    // Store the handle to unsubscribe from query updates.
    @State private var querySub: AnyCancellable?

    var body: some View {
        VStack {
            // Use the query results in a View.
            ForEach(queryRef.data?.movies ?? [], id: \.id) { movie in
                    Text(movie.title)
                }
        }
        .onAppear {
            // Subscribe to the query for updates using the Observable macro.
            Task {
                do {
                    querySub = try await queryRef.subscribe().sink { _ in }
                } catch {
                    print("Error subscribing to query: \(error)")
                }
            }
        }
        .onDisappear {
          querySub?.cancel()
        }
    }
}
```

### Data Type Mapping Reference

- GraphQL `UUID` -> Swift `UUID`
- GraphQL `Date` -> Swift `FirebaseDataConnect.LocalDate`
- GraphQL `Timestamp` -> Swift `FirebaseCore.Timestamp`
- GraphQL `Int` -> Swift `Int`
- GraphQL `Float` -> Swift `Double`
- GraphQL `Boolean` -> Swift `Bool`

SHA-256: cc972c288be5e0b833e1f7e4e9ced324e06e412f77086baef6630dab62f93a2c