RivetKit Swift 客戶端指南。用於使用 RivetKitClient 連接到 Rivet Actors、建立 Actor 控制代碼、呼叫動作或管理連線的 Swift 客戶端。
RivetKit Swift 客戶端
當您建立連接到 Rivet Actors 的 Swift 客戶端時,請使用此技能,搭配 RivetKitClient。
版本
RivetKit 版本:2.3.4
錯誤處理原則
- 預設偏好快速失敗(fail-fast)行為。
- 除非絕對必要,否則避免使用寬泛的
do/catch。 - 如果使用了 catch 區塊,請明確處理錯誤,至少記錄下來。
安裝
加入 Swift 套件依賴並匯入 RivetKitClient:
// Package.swift
dependencies: [
.package(url: "https://github.com/rivet-dev/rivetkit-swift", from: "2.0.0")
]
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "RivetKitClient", package: "rivetkit-swift")
]
)
]
最小客戶端
端點 URL
import RivetKitClient
let config = try ClientConfig(
endpoint: "https://my-namespace:pk_...@api.rivet.dev"
)
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("counter", ["my-counter"])
let count: Int = try await handle.action("increment", 1, as: Int.self)
明確欄位
import RivetKitClient
let config = try ClientConfig(
endpoint: "https://api.rivet.dev",
namespace: "my-namespace",
token: "pk_..."
)
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("counter", ["my-counter"])
let count: Int = try await handle.action("increment", 1, as: Int.self)
無狀態 vs 有狀態
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("counter", ["my-counter"])
// 無狀態:每次呼叫獨立
let current: Int = try await handle.action("getCount", as: Int.self)
print("目前計數:\(current)")
// 有狀態:保持連線以接收即時事件
let conn = handle.connect()
// 使用 AsyncStream 訂閱事件
let eventTask = Task {
for await count in await conn.events("count", as: Int.self) {
print("事件:\(count)")
}
}
_ = try await conn.action("increment", 1, as: Int.self)
eventTask.cancel()
await conn.dispose()
await client.dispose()
取得 Actors
import RivetKitClient
struct GameInput: Encodable {
let mode: String
}
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
// 取得或建立一個 actor
let room = client.getOrCreate("chatRoom", ["room-42"])
// 取得現有 actor(若找不到則失敗)
let existing = client.get("chatRoom", ["room-42"])
// 建立新 actor 並帶入輸入
let created = try await client.create(
"game",
["game-1"],
options: CreateOptions(input: GameInput(mode: "ranked"))
)
// 根據 ID 取得 actor
let byId = client.getForId("chatRoom", "actor-id")
// 解析 actor ID
let resolvedId = try await room.resolve()
print("解析後的 ID:\(resolvedId)")
await client.dispose()
動作支援 0 到 5 個參數的位置多載:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("counter", ["my-counter"])
let count: Int = try await handle.action("getCount")
let updated: String = try await handle.action("rename", "new-name")
let ok: Bool = try await handle.action("setScore", "user-1", 42)
print("計數:\(count),更新後:\(updated),結果:\(ok)")
await client.dispose()
如果需要超過 5 個參數,請使用原始 JSON 備援:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("counter", ["my-counter"])
let args: [JSONValue] = [
.string("user-1"),
.number(.int(42)),
.string("extra"),
.string("more"),
.string("args"),
.string("here")
]
let ok: Bool = try await handle.action("setScore", args: args, as: Bool.self)
print("結果:\(ok)")
await client.dispose()
連線參數
import RivetKitClient
struct ConnParams: Encodable {
let authToken: String
}
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let chat = client.getOrCreate(
"chatRoom",
["general"],
options: GetOrCreateOptions(params: ConnParams(authToken: "jwt-token-here"))
)
let conn = chat.connect()
// 使用連線...
for await status in await conn.statusChanges() {
print("狀態:\(status.rawValue)")
if status == .connected {
break
}
}
await conn.dispose()
await client.dispose()
訂閱事件
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let conn = client.getOrCreate("chatRoom", ["general"]).connect()
// 使用 AsyncStream 訂閱事件
let messageTask = Task {
for await (from, body) in await conn.events("message", as: (String, String).self) {
print("\(from):\(body)")
}
}
// 一次性事件,收到後中斷
let gameOverTask = Task {
for await _ in await conn.events("gameOver", as: Void.self) {
print("完成")
break
}
}
// 讓它跑一段時間
try await Task.sleep(for: .seconds(5))
// 完成時取消
messageTask.cancel()
gameOverTask.cancel()
await conn.dispose()
await client.dispose()
事件串流支援 0 到 5 個型別參數。如果需要原始值或超過 5 個參數,請使用 JSONValue:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let conn = client.getOrCreate("chatRoom", ["general"]).connect()
let rawTask = Task {
for await args in await conn.events("message") {
print(args)
}
}
try await Task.sleep(for: .seconds(5))
rawTask.cancel()
await conn.dispose()
await client.dispose()
連線生命週期
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let conn = client.getOrCreate("chatRoom", ["general"]).connect()
// 監控狀態變化(立即產生目前狀態)
let statusTask = Task {
for await status in await conn.statusChanges() {
print("狀態:\(status.rawValue)")
}
}
// 監控錯誤
let errorTask = Task {
for await error in await conn.errors() {
print("錯誤:\(error.group).\(error.code)")
}
}
// 監控開啟/關閉事件
let openTask = Task {
for await _ in await conn.opens() {
print("已連線")
}
}
let closeTask = Task {
for await _ in await conn.closes() {
print("已斷線")
}
}
// 檢查目前狀態
let current = await conn.currentStatus
print("目前狀態:\(current.rawValue)")
// 讓它跑一段時間
try await Task.sleep(for: .seconds(5))
// 清理
statusTask.cancel()
errorTask.cancel()
openTask.cancel()
closeTask.cancel()
await conn.dispose()
await client.dispose()
低階 HTTP 與 WebSocket
對於實作 onRequest 或 onWebSocket 的 actors,可以直接呼叫:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("chatRoom", ["general"])
// 原始 HTTP 請求
let response = try await handle.fetch("history")
let history: [String] = try response.json([String].self)
print("歷史記錄:\(history)")
// 原始 WebSocket 連線
let websocket = try await handle.websocket(path: "stream")
try await websocket.send(text: "hello")
let message = try await websocket.receive()
print("收到:\(message)")
await client.dispose()
從後端呼叫
在伺服器端 Swift(Vapor、Hummingbird 等)中使用相同的客戶端:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("counter", ["server-counter"])
let count: Int = try await handle.action("increment", 1, as: Int.self)
print("計數:\(count)")
await client.dispose()
錯誤處理
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
do {
_ = try await client.getOrCreate("user", ["user-123"])
.action("updateUsername", "ab", as: String.self)
} catch let error as ActorError {
print("錯誤代碼:\(error.code)")
print("中繼資料:\(String(describing: error.metadata))")
}
await client.dispose()
如果需要未型別的回應,可以解碼為 JSONValue:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
let handle = client.getOrCreate("data", ["raw"])
let value: JSONValue = try await handle.action("getRawPayload")
print("原始值:\(value)")
await client.dispose()
概念
鍵值
鍵值唯一識別 actor 實例。使用複合鍵值(陣列)進行階層式定址:
import RivetKitClient
let config = try ClientConfig(endpoint: "http://localhost:6420")
let client = RivetKitClient(config: config)
// 使用複合鍵值進行階層式定址
let room = client.getOrCreate("chatRoom", ["org-acme", "general"])
let actorId = try await room.resolve()
print("Actor ID:\(actorId)")
await client.dispose()
不要使用字串插值(如 "org:\(userId)")來建立鍵值,因為 userId 可能包含使用者資料。請改用陣列以防止鍵值注入攻擊。
環境變數
ClientConfig 會從環境變數讀取選用值:
RIVET_NAMESPACE- 命名空間(也可放在端點 URL 中)RIVET_TOKEN- 驗證令牌(也可放在端點 URL 中)RIVET_RUNNER- Runner 名稱(預設為"default")
endpoint 參數永遠是必要的。沒有預設端點。
端點格式
端點支援 URL 驗證語法:
https://namespace:token@api.rivet.dev
您也可以傳入不含驗證資訊的端點,並分別提供 RIVET_NAMESPACE 和 RIVET_TOKEN。對於無伺服器部署,請將端點設為您應用程式的 /api/rivet URL。詳情請參閱端點。
API 參考
客戶端
RivetKitClient(config:)- 使用設定建立客戶端ClientConfig- 設定端點、命名空間和令牌client.get()/getOrCreate()/getForId()/create()- 取得 actor 控制代碼client.dispose()- 釋放客戶端及所有連線
ActorHandle
handle.action(name, args..., as:)- 無狀態動作呼叫handle.connect()- 建立有狀態連線handle.resolve()- 取得 actor IDhandle.getGatewayUrl()- 取得原始閘道 URLhandle.fetch(path, request:)- 原始 HTTP 請求handle.websocket(path:)- 原始 WebSocket 連線
ActorConnection
conn.action(name, args..., as:)- 透過 WebSocket 呼叫動作conn.events(name, as:)- 型別事件的 AsyncStreamconn.statusChanges()- 狀態變化的 AsyncStreamconn.errors()- 連線錯誤的 AsyncStreamconn.opens()- 連線開啟時產生事件的 AsyncStreamconn.closes()- 連線關閉時產生事件的 AsyncStreamconn.currentStatus- 目前連線狀態conn.dispose()- 關閉連線
型別
ActorConnStatus- 連線狀態列舉(.idle、.connecting、.connected、.disconnected、.disposed)ActorError- 型別化的 actor 錯誤,包含group、code、message、metadataJSONValue- 用於未型別回應的原始 JSON 值
需要更多客戶端功能?
如果您需要更多關於 Rivet Actors、註冊表或伺服器端 RivetKit 的資訊,請加入主要技能:
npx skills add rivet-dev/skills
然後使用 rivetkit 技能取得後端指引。






