claudegoodies
Skill

swift-actor-persistence

From affaan-m

Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design.

Provides a generic Swift actor pattern for an in-memory-cached, file-backed data repository with atomic writes.

Use it when

  • Building a local persistence layer in Swift 5.9+ on iOS 17+/macOS 14+
  • Replacing DispatchQueue/NSLock synchronization with actor-based concurrency
  • Building offline-first apps that cache data locally before syncing
  • Need thread-safe shared mutable state accessed from multiple app parts

Skip it if

  • Targets Swift 5.9+/iOS 17+/macOS 14+ only, not older platforms
  • Whole-file JSON encode/decode on every save, not suited for large datasets or complex queries
  • Just one code pattern/template, not a library or installable package

Facts

Repository
affaan-m/ECC
Status
Actively maintained
Last commit

Source preview

The instructions Claude Code reads when this skill runs.

# Swift Actors for Thread-Safe Persistence

Patterns for building thread-safe data persistence layers using Swift actors. Combines in-memory caching with file-backed storage, leveraging the actor model to eliminate data races at compile time.

## When to Activate

- Building a data persistence layer in Swift 5.9+ (iOS 17+, macOS 14+)
- Need thread-safe access to shared mutable state
- Want to eliminate manual synchronization (locks, DispatchQueues)
- Building offline-first apps with local storage

## Core Pattern

### Actor-Based Repository

The actor model guarantees serialized access — no data races, enforced by the compiler.

```swift
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 {
        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]
    }

    
View full source on GitHub →

Other skills