Source profileQuality 65/100

affaan-m/ECC/docs/ja-JP/skills/swift-actor-persistence/SKILL.md

swift-actor-persistence

Review swift-actor-persistence's use cases, installation, workflow, and original source instructions.

Source repository stars
234,327
Declared platforms
0
Static risk flags
1
Last source update
2026-07-27
Source checked
2026-07-28

Decision brief

What it does—and where it fits

Swiftのactorを使用してスレッドセーフなデータ永続化レイヤーを構築するパターン。メモリキャッシュとファイルバックドストレージを組み合わせ、actorモデルを活用してコンパイル時にデータ競合を排除する。

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/affaan-m/ECC --skill "docs/ja-JP/skills/swift-actor-persistence"
    Safe inspection promptEditorial

    Inspect the Agent Skill "swift-actor-persistence" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/ja-JP/skills/swift-actor-persistence/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      起動条件

      Swift 5.5以降でデータ永続化レイヤーを構築する場合 共有可変状態へのスレッドセーフアクセスが必要な場合 手動の同期(ロック、DispatchQueue)を排除したい場合 ローカルストレージを持つオフラインファースとアプリを構築する場合

      Swift 5.5以降でデータ永続化レイヤーを構築する場合共有可変状態へのスレッドセーフアクセスが必要な場合手動の同期(ロック、DispatchQueue)を排除したい場合
    2. 02

      コアパターン

      Actorモデルはシリアライズされたアクセスを保証する——コンパイラによって強制されるデータ競合なし。

      Actorモデルはシリアライズされたアクセスを保証する——コンパイラによって強制されるデータ競合なし。Actorの分離により、すべての呼び出しは自動的に非同期になる:
    3. 03

      Actorベースのリポジトリ

      Actorモデルはシリアライズされたアクセスを保証する——コンパイラによって強制されるデータ競合なし。

      Actorモデルはシリアライズされたアクセスを保証する——コンパイラによって強制されるデータ競合なし。
    4. 04

      使い方

      Actorの分離により、すべての呼び出しは自動的に非同期になる:

      Actorの分離により、すべての呼び出しは自動的に非同期になる:

    Permission review

    Static risk signals and limitations

    Writes files

    medium · line 91

    The documentation asks the agent to create, modify, or delete local files.

    // Write — updates cache and persists to file atomically

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score65/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars234,327SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    affaan-m/ECC
    Skill path
    docs/ja-JP/skills/swift-actor-persistence/SKILL.md
    Commit
    4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38
    License
    MIT
    Collected
    2026-07-28
    Default branch
    main
    View the original SKILL.md

    スレッドセーフな永続化のための Swift Actor

    Swiftのactorを使用してスレッドセーフなデータ永続化レイヤーを構築するパターン。メモリキャッシュとファイルバックドストレージを組み合わせ、actorモデルを活用してコンパイル時にデータ競合を排除する。

    起動条件

    • Swift 5.5以降でデータ永続化レイヤーを構築する場合
    • 共有可変状態へのスレッドセーフアクセスが必要な場合
    • 手動の同期(ロック、DispatchQueue)を排除したい場合
    • ローカルストレージを持つオフラインファースとアプリを構築する場合

    コアパターン

    Actorベースのリポジトリ

    Actorモデルはシリアライズされたアクセスを保証する——コンパイラによって強制されるデータ競合なし。

    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)
            // Synchronous load during init (actor isolation not yet active)
            self.cache = Self.loadSynchronously(from: fileURL)
        }
    
        // MARK: - Public API
    
        public func save(_ item: T) throws {
            let previous = cache[item.id]
            cache[item.id] = item
            do {
                try persistToFile()
            } catch {
                // ディスク書き込み失敗時はキャッシュをロールバックして整合性を維持
                cache[item.id] = previous
                throw error
            }
        }
    
        public func delete(_ id: String) throws {
            let previous = cache[id]
            cache[id] = nil
            do {
                try persistToFile()
            } catch {
                // ディスク書き込み失敗時はキャッシュをロールバックして整合性を維持
                cache[id] = previous
                throw error
            }
        }
    
        public func find(by id: String) -> T? {
            cache[id]
        }
    
        public func loadAll() -> [T] {
            Array(cache.values)
        }
    
        // MARK: - Private
    
        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の分離により、すべての呼び出しは自動的に非同期になる:

    let repository = LocalRepository<Question>()
    
    // Read — fast O(1) lookup from in-memory cache
    let question = await repository.find(by: "q-001")
    let allQuestions = await repository.loadAll()
    
    // Write — updates cache and persists to file atomically
    try await repository.save(newQuestion)
    try await repository.delete("q-001")
    

    @Observable ViewModel との組み合わせ

    @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を使用(クラス + ロックではなく)コンパイラによって強制されるスレッド安全性、手動同期不要
    メモリキャッシュ + ファイル永続化キャッシュからの高速読み取り、ディスクへの永続的な書き込み
    初期化時の同期ロード非同期初期化の複雑さを回避
    IDをキーとする辞書識別子によるO(1)検索
    ジェネリック Codable & Identifiableあらゆるモデル型で再利用可能
    アトミックなファイル書き込み(.atomicクラッシュ時の部分書き込みを防ぐ

    ベストプラクティス

    • Actorの境界を越えるすべてのデータに Sendable 型を使用する
    • Actorのパブリックなアビリティを最小化する —— 永続化の詳細ではなく、ドメイン操作のみを公開する
    • .atomic 書き込みを使用する —— 書き込み中のアプリクラッシュによるデータ破損を防ぐ
    • init で同期的にロードする —— 非同期イニシャライザはローカルファイルに対するわずかな利点のために複雑さが増す
    • @Observable ViewModelと組み合わせる —— リアクティブなUI更新を実現する

    避けるべきアンチパターン

    • Swiftの新しい並行処理コードでActorの代わりに DispatchQueue または NSLock を使用する
    • 内部のキャッシュ辞書を外部の呼び出し元に公開する
    • 初期化後にファイルURLを外部から変更可能にする(初期化時のみ設定を許可すること)
    • すべてのActor メソッド呼び出しが await であることを忘れる——呼び出し元は非同期コンテキストを処理する必要がある
    • Actor の分離をバイパスするために nonisolated を使用する(本末転倒)

    使用場面

    • iOS/macOSアプリのローカルデータストレージ(ユーザーデータ、設定、キャッシュコンテンツ)
    • 後でサーバーと同期するオフラインファーストアーキテクチャ
    • アプリの複数の部分から並行アクセスされる共有可変状態
    • DispatchQueue ベースのレガシーなスレッド安全機構を最新のSwift並行処理に置き換える

    Alternatives

    Compare before choosing