SKILL.md
readonly只读
name
rivetkit-client-swift
description
RivetKit Swift 客户端指南。用于通过 RivetKitClient 连接 Rivet Actors 的 Swift 客户端,创建 actor 句柄、调用操作或管理连接。
RivetKit Swift 客户端
在构建通过 RivetKitClient 连接 Rivet Actors 的 Swift 客户端时使用此技能。
版本
RivetKit 版本:2.3.4
错误处理策略
- 默认优先快速失败。
- 除非绝对必要,避免使用宽泛的
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)
无状态与有状态
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:\(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:\(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 的 actor,可以直接调用:
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- 运行器名称(默认为"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 技能获取后端指导。






