Pular para o conteúdo
Skillpedia
APIs e servidores (backend)280 mil · #124

swift-actor-persistence

Faz seu agente gerenciar dados de forma segura em Swift. Ele usa 'actors' para evitar problemas de concorrência, garantindo que os dados não sejam corrompidos.

O que ela faz

Este código ajuda a guardar informações importantes no seu aplicativo de forma segura, mesmo que várias partes do app tentem acessar ao mesmo tempo. Ele salva os dados na memória para acesso rápido e também em um arquivo para não se perder.

Quando usar

  • ✓Guardar dados do usuário em um app.
  • ✓Criar apps que funcionam sem internet.
  • ✓Evitar que dados se corrompam quando o app é usado em vários lugares ao mesmo tempo.

Exemplo do que pedir para a IA

“Salve as informações do usuário neste app.”

Quer saber mais? Abra as seções abaixo.

Como usar

O jeito mais fácil: copie a mensagem abaixo e cole no Claude, ChatGPT, Cursor ou outra IA. Ela lê a skill e segue as instruções.

Link da skill

https://github.com/affaan-m/ECC/blob/main/pi/core/skills/swift-actor-persistence/SKILL.md

Mensagem pronta para colar

Use esta skill para me ajudar: https://github.com/affaan-m/ECC/blob/main/pi/core/skills/swift-actor-persistence/SKILL.md Leia o arquivo SKILL.md desse link e siga as instruções dele na minha tarefa.
Como funciona

Ele usa uma técnica chamada 'atores' que garante que apenas uma parte do código mexa nos dados por vez. Assim, evita confusão e erros. Os dados ficam na memória para serem rápidos e são salvos em um arquivo para segurança.

Instalação

Jeito mais fácil: copie o link da skill e cole no Claude, ChatGPT ou Cursor pedindo para seguir as instruções.

No terminal (Claude Code, Codex, Cursor), na pasta do projeto:

npx skills add affaan-m/ECC --skill swift-actor-persistence

Ou baixe só o arquivo:

curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/swift-actor-persistence/SKILL.md -o SKILL.md
Conteúdo técnico (SKILL.md)

Tradução do texto original do autor no GitHub. Os comandos e códigos estão como no original.

Swift Actors para Persistência Thread-Safe

Padrões para construir camadas de persistência de dados thread-safe usando actors do Swift. Combina cache em memória com armazenamento em arquivo, aproveitando o modelo de actors para eliminar data races em tempo de compilação.

Quando Ativar

  • Construindo uma camada de persistência de dados em Swift 5.5+
  • Necessidade de acesso thread-safe a estado mutável compartilhado
  • Desejo de eliminar sincronização manual (locks, DispatchQueues)
  • Construindo apps offline-first com armazenamento local

Padrão Central

Repositório Baseado em Actor

O modelo de actors garante acesso serializado — sem data races, imposto pelo compilador.

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

Uso

Todas as chamadas são automaticamente async devido ao isolamento do 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")

Combinando com ViewModel @Observable

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

Principais Decisões de Design

Decisão Racional
Actor (não classe + lock) Thread safety imposta pelo compilador, sem sincronização manual
Cache em memória + persistência em arquivo Leituras rápidas do cache, escritas duráveis no disco
Carregamento síncrono em init Evita complexidade de inicialização async
Dicionário com chave por ID Consultas O(1) por identificador
Genérico sobre Codable & Identifiable Reutilizável em qualquer tipo de modelo
Escritas atômicas em arquivo (.atomic) Previne escritas parciais em caso de crash

Melhores Práticas

  • Use tipos Sendable para todos os dados que cruzam limites de actors
  • Mantenha a API pública do actor mínima — exponha apenas operações de domínio, não detalhes de persistência
  • Use escritas .atomic para prevenir corrupção de dados se o app travar no meio de uma escrita
  • Carregue síncronamente em init — inicializadores async adicionam complexidade com benefício mínimo para arquivos locais
  • Combine com ViewModels @Observable para atualizações reativas da UI

Anti-Padrões a Evitar

  • Usar DispatchQueue ou NSLock em vez de actors para novo código de concorrência Swift
  • Expor o dicionário de cache interno para chamadores externos
  • Tornar o URL do arquivo configurável sem validação
  • Esquecer que todas as chamadas de método de actor são await — os chamadores devem lidar com o contexto async
  • Usar nonisolated para contornar o isolamento do actor (anula o propósito)

Quando Usar

  • Armazenamento de dados local em apps iOS/macOS (dados do usuário, configurações, conteúdo em cache)
  • Arquiteturas offline-first que sincronizam com um servidor posteriormente

…

Perguntas frequentes

Por que usar 'atores' em vez de métodos normais?

Atores garantem que o código que mexe nos dados seja executado um de cada vez, de forma automática. Isso evita erros complicados de 'corrida de dados' que acontecem quando várias partes tentam mudar a mesma coisa ao mesmo tempo.

O que é 'persistência'?

Persistência significa guardar informações de forma que elas não se percam quando o aplicativo é fechado ou reiniciado. É como salvar um documento no computador.

Como os dados são salvos?

Os dados são guardados em um arquivo no formato JSON. Eles são salvos de forma 'atômica', o que significa que a escrita é feita de uma vez só, protegendo contra corrupção se o app travar durante o salvamento.

Detalhes

Descrição original do autor

Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design. Use when persisting data in Swift and a data race or thread-safety problem needs designing out.

repo: affaan-m/ECC

Popularidade

Estrelas no GitHub
280 mil
Posição no ranking
#124
Licença
MIT
Atualizada em
15/10/2026

Essa skill é útil?

0

Entre para votar.

Comentários

  • …

Mais skills deste repositório

Skills parecidas