6.4 KiB
| name | description | metadata | ||
|---|---|---|---|---|
| powersync-swift | PowerSync Swift SDK — schema, queries, sync lifecycle, backend connectors, and GRDB ORM support |
|
PowerSync Swift SDK
Load this when building a Swift app (iOS, macOS) with PowerSync.
Best practices and guidance for building apps with the PowerSync Swift SDK.
| Resource | Description |
|---|---|
| Swift API reference | Full API reference, consult only when the inline examples don't cover your case. |
| Supported Platforms | Supported platforms and features, consult for compatibility details. |
Installation
| Method | Instructions |
|---|---|
Package.swift |
Installation - Package.swift |
| Xcode | Installation - Xcode |
Setup
1. Define Schema
import PowerSync
let lists = Table(
name: "lists",
columns: [
// id column is automatically included
.text("name"),
.text("created_at"),
.text("owner_id")
]
)
let todos = Table(
name: "todos",
columns: [
.text("list_id"),
.text("description"),
.integer("completed"), // 0 or 1
.text("created_at"),
.text("completed_at"),
.text("created_by"),
.text("completed_by")
],
indexes: [
Index(name: "list_id", columns: [IndexedColumn.ascending("list_id")])
]
)
let AppSchema = Schema(tables: [lists, todos])
See Define the Client-Side Schema for more information.
2. Create Backend Connector
import PowerSync
@Observable
@MainActor
final class MyConnector: PowerSyncBackendConnectorProtocol {
private let apiClient: APIClient
init(apiClient: APIClient) {
self.apiClient = apiClient
}
func fetchCredentials() async throws -> PowerSyncCredentials? {
let response = try await apiClient.getPowerSyncToken()
return PowerSyncCredentials(
endpoint: "https://your-instance.powersync.journeyapps.com",
token: response.token,
expiresAt: response.expiresAt
)
}
func uploadData(database: PowerSyncDatabaseProtocol) async throws {
guard let transaction = try await database.getNextCrudTransaction() else { return }
do {
for entry in transaction.crud {
switch entry.op {
case .put:
var data = entry.opData ?? [:]
data["id"] = entry.id
try await apiClient.upsert(table: entry.table, id: entry.id, data: data)
case .patch:
guard let opData = entry.opData else { continue }
try await apiClient.update(table: entry.table, id: entry.id, data: opData)
case .delete:
try await apiClient.delete(table: entry.table, id: entry.id)
}
}
try await transaction.complete()
} catch {
throw error
}
}
}
Use getCrudBatch instead of getNextCrudTransaction when uploading large numbers of mutations in bulk.
See Integrate with your Backend for more information.
3. Instantiate and Connect
@Observable
@MainActor
final class SystemManager {
let connector = MyConnector()
let db: PowerSyncDatabaseProtocol
init() {
db = PowerSyncDatabase(
schema: AppSchema,
dbFilename: "powersync-swift.sqlite"
)
}
func connect() async throws {
try await db.connect(connector: connector)
}
}
See Instantiate the PowerSync Database for more information.
Sync Streams
See sync-config.md for how to subscribe to Sync Streams when auto_subscribe is not set to true in the PowerSync Service config.
Query Patterns
See Using PowerSync: CRUD for the full API reference.
One-Time Queries
// Fetch all matching rows
let todos = try await db.getAll("SELECT * FROM todos WHERE list_id = ?", parameters: [listId])
// Fetch single row — throws if not found
let todo = try await db.get("SELECT * FROM todos WHERE id = ?", parameters: [id])
// Fetch single row — returns nil if not found
let todo = try await db.getOptional("SELECT * FROM todos WHERE id = ?", parameters: [id])
Reactive Queries
// Watch a query — emits on every change to the watched tables
for try await todos in db.watch("SELECT * FROM todos WHERE list_id = ?", parameters: [listId]) {
// update UI
}
Writing Data
// Single mutation
try await db.execute(
"INSERT INTO todos (id, description, completed) VALUES (uuid(), ?, ?)",
parameters: ["New todo", 0]
)
// Multiple related mutations as a single unit
try await db.writeTransaction { tx in
try await tx.execute("INSERT INTO lists (id, name) VALUES (?, ?)", parameters: [listId, "Shopping"])
try await tx.execute("INSERT INTO todos (id, list_id, description) VALUES (uuid(), ?, ?)", parameters: [listId, "Milk"])
}
ORM — GRDB
PowerSync Swift supports GRDB as an ORM. Requires PowerSync Swift v1.9.0+.
Setup requires a DatabasePool with PowerSync config — see GRDB Setup.
// Define a GRDB record type
struct Todo: Codable, Identifiable, FetchableRecord, PersistableRecord {
var id: String
var description: String
var completed: Int
}
// Read
let todos = try await pool.read { db in
try Todo.fetchAll(db)
}
// Write
try await pool.write { db in
var todo = Todo(id: UUID().uuidString, description: "Buy milk", completed: 0)
try todo.insert(db)
}
See GRDB Architecture for how the PowerSync + GRDB integration works.