swift-actor-persistence
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSwift Actors for Thread-Safe Persistence
用于线程安全持久化的Swift Actors
スレッドセーフな永続化のためのSwift Actor
—
Extracted / 抽出日: 2026-02-05
Context / コンテキスト: iOS/Swift apps requiring thread-safe data persistence with async/await
async/awaitを使用したスレッドセーフなデータ永続化が必要なiOS/Swiftアプリ
提取日期: 2026-02-05
适用场景: 需要使用async/await实现线程安全数据持久化的iOS/Swift应用
Problem / 課題
问题
Data persistence layers often face race conditions when multiple parts of an app read/write simultaneously. Traditional approaches (DispatchQueues, locks) are error-prone and verbose.
データ永続化レイヤーは、アプリの複数の部分が同時に読み書きする際にレースコンディションに直面することが多い。従来のアプローチ(DispatchQueues、ロック)はエラーが発生しやすく、冗長になりがち。
数据持久化层在应用的多个部分同时进行读写操作时,经常会遇到竞态条件问题。传统的解决方案(如DispatchQueues、锁)容易出错且代码冗长。
Solution / 解決策
解决方案
Use Swift actors to isolate all persistence state and operations. The actor model guarantees:
- No data races (compiler-enforced)
- Automatic serialization of access
- Async-first API that integrates with structured concurrency
Swift actorを使用して、すべての永続化状態と操作を分離する。actorモデルは以下を保証:
- データ競合なし(コンパイラによる強制)
- アクセスの自動シリアライズ
- 構造化並行性と統合されたasyncファーストAPI
swift
public actor LocalRepository {
private var cache: [String: Record] = [:]
private let cacheFileURL: URL
public init(directory: URL = .documentsDirectory) {
self.cacheFileURL = directory.appendingPathComponent("cache.json")
// Synchronous cache load during init (actor isolation not yet active)
// init中の同期キャッシュ読み込み(actor分離がまだアクティブでないため)
self.cache = Self.loadCacheSynchronously(from: cacheFileURL)
}
public func save(_ record: Record) throws {
cache[record.id] = record
try persistToFile()
}
public func loadAll() -> [Record] {
Array(cache.values)
}
public func find(by id: String) -> Record? {
cache[id]
}
private func persistToFile() throws {
let data = try JSONEncoder().encode(Array(cache.values))
try data.write(to: cacheFileURL)
}
private static func loadCacheSynchronously(from url: URL) -> [String: Record] {
guard let data = try? Data(contentsOf: url),
let records = try? JSONDecoder().decode([Record].self, from: data) else {
return [:]
}
return Dictionary(uniqueKeysWithValues: records.map { ($0.id, $0) })
}
}使用Swift Actor来隔离所有持久化状态和操作。Actor模型可以保证:
- 无数据竞争(由编译器强制保障)
- 自动序列化访问
- 与结构化并发集成的异步优先API
swift
public actor LocalRepository {
private var cache: [String: Record] = [:]
private let cacheFileURL: URL
public init(directory: URL = .documentsDirectory) {
self.cacheFileURL = directory.appendingPathComponent("cache.json")
// init中の同期キャッシュ読み込み(actor分離がまだアクティブでないため)
self.cache = Self.loadCacheSynchronously(from: cacheFileURL)
}
public func save(_ record: Record) throws {
cache[record.id] = record
try persistToFile()
}
public func loadAll() -> [Record] {
Array(cache.values)
}
public func find(by id: String) -> Record? {
cache[id]
}
private func persistToFile() throws {
let data = try JSONEncoder().encode(Array(cache.values))
try data.write(to: cacheFileURL)
}
private static func loadCacheSynchronously(from url: URL) -> [String: Record] {
guard let data = try? Data(contentsOf: url),
let records = try? JSONDecoder().decode([Record].self, from: data) else {
return [:]
}
return Dictionary(uniqueKeysWithValues: records.map { ($0.id, $0) })
}
}Key Patterns / 主要パターン
核心模式
- In-memory cache + file persistence / インメモリキャッシュ + ファイル永続化: Fast reads from cache, durable writes to disk / キャッシュからの高速読み取り、ディスクへの永続書き込み
- Synchronous init loading / 同期的な初期化読み込み: Avoids async initialization complexity / 非同期初期化の複雑さを回避
- Dictionary keying / Dictionary型によるキー管理: O(1) lookups by ID / IDによるO(1)の検索
- Private persistence / プライベートな永続化: External callers only see domain operations / 外部呼び出し元はドメイン操作のみを参照
- 内存缓存+文件持久化: 从缓存快速读取,写入磁盘保证持久化
- 同步初始化加载: 避免异步初始化的复杂性
- 字典键值管理: 通过ID实现O(1)时间复杂度的查找
- 私有持久化实现: 外部调用者仅能看到领域相关操作
Usage / 使用方法
使用方法
swift
let repository = LocalRepository()
// All calls are async due to actor isolation
// actor分離により、すべての呼び出しは非同期
let records = await repository.loadAll()
try await repository.save(newRecord)
let found = await repository.find(by: "question-1")swift
let repository = LocalRepository()
// 由于Actor隔离机制,所有调用均为异步
let records = await repository.loadAll()
try await repository.save(newRecord)
let found = await repository.find(by: "question-1")When to Use / 使用すべき場面
适用场景
- Building a data persistence layer in Swift 5.5+ / Swift 5.5以降でデータ永続化レイヤーを構築する場合
- Need thread-safe access to shared state / 共有状態へのスレッドセーフなアクセスが必要な場合
- Want to avoid manual synchronization (locks, queues) / 手動同期(ロック、キュー)を避けたい場合
- Building offline-first apps with local storage / ローカルストレージを使用したオフラインファーストアプリを構築する場合
- 在Swift 5.5及以上版本中构建数据持久化层时
- 需要对共享状态进行线程安全访问时
- 希望避免手动同步(锁、队列)时
- 构建基于本地存储的离线优先应用时
Related Patterns / 関連パターン
相关模式
- Combine with ViewModels for UI binding / UIバインディング用に
@ObservableViewModelと組み合わせる@Observable - Use types for data crossing actor boundaries / actor境界を越えるデータには
Sendable型を使用Sendable - Consider actor for cloud sync operations / クラウド同期操作には
FileBasedSyncManageractorを検討FileBasedSyncManager
- 与ViewModel结合用于UI绑定
@Observable - 跨Actor边界的数据使用类型
Sendable - 云同步操作可考虑使用Actor
FileBasedSyncManager