生产级 API 的 REST API 设计模式,包括资源命名、状态码、分页、过滤、错误响应、版本控制和速率限制。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Swift 中使用 actor 实现的线程安全数据持久化 —— 结合内存缓存与文件存储,从设计上消除数据竞争。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
使用 Swift actor 构建线程安全数据持久化层的模式。该模式结合了内存缓存(In-memory caching)与基于文件的存储,利用 actor 模型(Actor model)在编译时消除数据竞争(Data races)。
Actor 模型保证了序列化访问(Serialized access)—— 由编译器强制执行,确保不会出现数据竞争。
public actor LocalRepository<T: Codable & Identifiable> where T.ID == String {
private var cache: [String: T] = [:]
private let fileURL: URL
public init(directory: URL = .documentsDirectory, filename: String = "data.json") {
self.fileURL = directory.appendingPathComponent(filename)
// 在 init 期间同步加载(此时 actor 隔离尚未生效)
self.cache = Self.loadSynchronously(from: fileURL)
}
// MARK: - 公共 API
public func save(_ item: T) throws {
cache[item.id] = item
try persistToFile()
}
public func delete(_ id: String) throws {
cache[id] = nil
try persistToFile()
}
public func find(by id: String) -> T? {
cache[id]
}
public func loadAll() -> [T] {
Array(cache.values)
}
// MARK: - 私有方法
private func persistToFile() throws {
let data = try JSONEncoder().encode(Array(cache.values))
try data.write(to: fileURL, options: .atomic)
}
private static func loadSynchronously(from url: URL) -> [String: T] {
guard let data = try? Data(contentsOf: url),
let items = try? JSONDecoder().decode([T].self, from: data) else {
return [:]
}
return Dictionary(uniqueKeysWithValues: items.map { ($0.id, $0) })
}
}
由于 actor 隔离(Actor isolation),所有调用都会自动变为异步:
let repository = LocalRepository<Question>()
// 读取 —— 从内存缓存中进行快速 O(1) 查找
let question = await repository.find(by: "q-001")
let allQuestions = await repository.loadAll()
// 写入 —— 原子化地更新缓存并持久化到文件
try await repository.save(newQuestion)
try await repository.delete("q-001")
@Observable
final class QuestionListViewModel {
private(set) var questions: [Question] = []
private let repository: LocalRepository<Question>
init(repository: LocalRepository<Question> = LocalRepository()) {
self.repository = repository
}
func load() async {
questions = await repository.loadAll()
}
func add(_ question: Question) async throws {
try await repository.save(question)
questions = await repository.loadAll()
}
}
| 决策 | 理由 |
|---|---|
| 使用 Actor (而非 class + lock) | 编译器强制执行线程安全,无需手动同步 |
| 内存缓存 + 文件持久化 | 缓存提供快速读取,磁盘提供持久化写入 |
| 在 init 中同步加载 | 避免异步初始化的复杂性,且对本地文件影响较小 |
| 以 ID 为键的字典 (Dictionary) | 通过标识符进行 O(1) 查找 |
泛型支持 Codable & Identifiable | 可在任何模型类型中复用 |
原子化文件写入 (.atomic) | 防止崩溃时出现部分写入导致的数据损坏 |
Sendable 类型.atomic 写入 以防止应用在写入过程中崩溃导致数据损坏init 中同步加载 —— 异步初始化会增加复杂性,而对本地文件的同步读取收益更高@Observable ViewModel 实现响应式 UI 更新DispatchQueue 或 NSLock 而非 actorawait 的 —— 调用者必须处理异步上下文nonisolated 绕过 actor 隔离(这违背了使用 actor 的初衷)DispatchQueue 的线程安全方案아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
生产级 API 的 REST API 设计模式,包括资源命名、状态码、分页、过滤、错误响应、版本控制和速率限制。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
REST API设计模式,包括资源命名、状态码、分页、过滤、错误响应、版本控制和生产API的速率限制。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
编写文章、指南、博客、教程、时事通讯(Newsletter)等长内容,支持从示例或品牌指南中提取独特的语感语调。适用于需要撰写超过一个段落的精炼文本,尤其是对语气一致性、结构和可信度有较高要求时。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
根据提供的示例或品牌指导,以独特的语气撰写文章、指南、博客帖子、教程、新闻简报等长篇内容。当用户需要超过一段的精致书面内容时使用,尤其是当语气一致性、结构和可信度至关重要时。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
撰写文章、指南、博客、教程、时事通讯等长篇内容,并根据提供的示例或品牌指南呈现独特的语言风格。当用户需要篇幅超过一段的精炼文字,且重视风格一致性、结构和可信度时,请使用此技能。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
编写文章、指南、博客帖子、教程、新闻通讯(newsletter)以及其他长篇内容。这些内容具有从提供的示例或品牌指南中提取出的独特语气。当用户需要比段落更长的精美文案,且对语气一致性、结构和可信度有要求时,请使用此技能(Skill)。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.