Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
affaan-m avatar

Swift Actor Persistence

  • 5.6k installs
  • 238k repo stars
  • Updated August 5, 2026
  • affaan-m/everything-claude-code

Swift Actor Persistence is an agent skill that teaches thread-safe local data layers in Swift using actors, in-memory caching, and atomic file storage.

About

This skill teaches patterns for thread-safe data persistence in Swift 5.9+ using actors, combining an in-memory cache with file-backed JSON storage. The core pattern is a generic LocalRepository actor keyed by Identifiable IDs: synchronous load on init, O(1) reads from cache, and atomic file writes on save or delete. All public calls are async due to actor isolation, which replaces manual locks or DispatchQueue synchronization with compiler-enforced safety. The docs include a full actor implementation, usage examples, and integration with @Observable ViewModels for reactive UI updates. Design decisions cover Sendable types, minimal public APIs, atomic writes to prevent corruption, and anti-patterns like nonisolated bypasses. Activate when building offline-first iOS or macOS apps, local user data stores, or replacing legacy concurrency code with modern Swift actor-based repositories. The table of design decisions explains why actors beat class-plus-lock approaches and why dictionary keyed lookups keep reads fast while durable JSON on disk survives restarts.

  • Generic LocalRepository actor with Codable and Identifiable models
  • In-memory cache plus atomic JSON file persistence on disk
  • Compiler-enforced thread safety without locks or DispatchQueues
  • @Observable ViewModel integration for reactive SwiftUI updates
  • Anti-patterns guide covering nonisolated bypass and exposed caches

Swift Actor Persistence by the numbers

  • 5,646 all-time installs (skills.sh)
  • +220 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #29 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Security screen: MEDIUM risk (skills.sh audit)
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
At a glance

swift-actor-persistence capabilities & compatibility

Capabilities
swift actor repository · local json persistence · thread safe cache · swiftui integration
Use cases
frontend · database
From the docs

What swift-actor-persistence says it does

Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design.
SKILL.md
The actor model guarantees serialized access — no data races, enforced by the compiler.
SKILL.md
npx skills add https://github.com/affaan-m/everything-claude-code --skill swift-actor-persistence

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs5.6k
repo stars238k
Security audit3 / 3 scanners passed
Last updatedAugust 5, 2026
Repositoryaffaan-m/everything-claude-code

How do you store and read shared mutable app data in Swift without data races or manual synchronization?

Thread-safe Swift actor repository with in-memory cache and atomic file persistence for iOS and macOS apps.

Who is it for?

iOS or macOS developers on Swift 5.9+ building offline-first apps with local persistence and concurrent access.

Skip if: Server-side Swift services, Core Data or SwiftData migrations, or teams still targeting pre-actor Swift concurrency only.

When should I use this skill?

Building a data persistence layer in Swift 5.9+, needing thread-safe shared state, or replacing DispatchQueue locks with actors.

What you get

You get a reusable actor-based repository with fast cache reads, durable JSON writes, and async APIs ready for SwiftUI ViewModels.

  • Actor persistence layer code
  • File-backed storage pattern

By the numbers

  • Targets Swift 5.5+ actor concurrency model

Files

SKILL.mdMarkdownGitHub ↗

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.

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]
    }

    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(items.map { ($0.id, $0) }, uniquingKeysWith: { _, latest in latest })
    }
}

Usage

All calls are automatically async due to actor isolation:

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")

Combining with @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()
    }
}

Key Design Decisions

DecisionRationale
Actor (not class + lock)Compiler-enforced thread safety, no manual synchronization
In-memory cache + file persistenceFast reads from cache, durable writes to disk
Synchronous init loadingAvoids async initialization complexity
Dictionary keyed by IDO(1) lookups by identifier
Generic over Codable & IdentifiableReusable across any model type
Atomic file writes (.atomic)Prevents partial writes on crash

Best Practices

  • Use `Sendable` types for all data crossing actor boundaries
  • Keep the actor's public API minimal — only expose domain operations, not persistence details
  • Use `.atomic` writes to prevent data corruption if the app crashes mid-write
  • Load synchronously in `init` — async initializers add complexity with minimal benefit for local files
  • Combine with `@Observable` ViewModels for reactive UI updates

Anti-Patterns to Avoid

  • Using DispatchQueue or NSLock instead of actors for new Swift concurrency code
  • Exposing the internal cache dictionary to external callers
  • Making the file URL configurable without validation
  • Forgetting that all actor method calls are await — callers must handle async context
  • Using nonisolated to bypass actor isolation (defeats the purpose)

When to Use

  • Local data storage in iOS/macOS apps (user data, settings, cached content)
  • Offline-first architectures that sync to a server later
  • Any shared mutable state that multiple parts of the app access concurrently
  • Replacing legacy DispatchQueue-based thread safety with modern Swift concurrency

Related skills

Forks & variants (1)

Swift Actor Persistence has 1 known copy in the catalog totaling 1.4k installs. They canonicalize to this original listing.

FAQ

Why use an actor instead of a class with NSLock?

Actors give compiler-enforced serialized access, eliminating manual synchronization and data races without DispatchQueue or lock management.

Do all repository calls need await?

Yes. Actor isolation makes every public method async, so callers must use await for reads and writes across concurrency domains.

How does persistence survive app crashes?

Writes use JSONEncoder plus data.write with the .atomic option so partial files are not left on disk if the app terminates mid-write.

Is Swift Actor Persistence safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Mobile Developmentbackendfrontend

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.