Back to OSS
Swift Package 通信 / サーバー

swift-persistence

KeyValue / Secure / Document / Registry を束ねるプロトコル指向の永続化抽象レイヤー

Swift
persistencekeyvaluestorage

English | 日本語

SwiftPersistence

A protocol-oriented persistence abstraction layer for Swift

Swift Platforms License

Features

  • Protocol-Oriented - All persistence operations defined as abstract protocols for DI and testability
  • KeyValueStore - Type-safe UserDefaults abstraction (Codable support)
  • SecureStore - Safe Keychain wrapper (API key and credential protection)
  • DocumentStore - File-based CRUD (individual JSON files, atomic writes)
  • RegistryStore - Single JSON file registry pattern
  • KeyResolver - Multi-source fallback resolution: Info.plist → Keychain → UserDefaults
  • InMemory Test Doubles - Bundled InMemory implementations for all protocols

Installation

// Package.swift
dependencies: [
    .package(url: "https://github.com/no-problem-dev/swift-persistence.git", .upToNextMajor(from: "1.0.0"))
]

Module Structure

Import only the modules you need:

Module Purpose
PersistenceCore Protocols + error types (Foundation only, no external dependencies)
PersistenceUserDefaults UserDefaults-backed KeyValueStore implementation
PersistenceKeychain Keychain-backed SecureStore implementation
PersistenceFileSystem File-backed DocumentStore / RegistryStore implementations
PersistenceTesting 5 InMemory implementations (test DI doubles)

Quick Start

Key-Value Store (UserDefaults Abstraction)

import PersistenceUserDefaults

let store = UserDefaultsKeyValueStore()

// Save and retrieve Codable values
try await store.setValue("dark", forKey: "theme")
let theme: String? = try await store.string(forKey: "theme")

// Custom types supported
struct UserPrefs: Codable, Sendable {
    var fontSize: Int
    var language: String
}
try await store.setValue(UserPrefs(fontSize: 14, language: "en"), forKey: "prefs")
let prefs: UserPrefs? = try await store.value(forKey: "prefs", type: UserPrefs.self)

Secure Store (Keychain Abstraction)

import PersistenceKeychain

let secrets = KeychainSecureStore(service: "com.example.myapp")

// Securely store API keys
try await secrets.setString("sk-abc123...", forKey: "api_key")
let key = try await secrets.getString(forKey: "api_key")

Document Store (File-based CRUD)

import PersistenceFileSystem

struct Note: Codable, Identifiable, Sendable {
    let id: UUID
    var title: String
    var body: String
}

let store = try FileSystemDocumentStore<Note>(
    directory: documentsURL.appendingPathComponent("notes")
)

// CRUD operations
let note = Note(id: UUID(), title: "Memo", body: "Content")
try await store.save(note)
let all = try await store.loadAll()
try await store.delete(id: note.id)

Registry Store (Single JSON Registry)

import PersistenceFileSystem

struct CacheEntry: Codable, Sendable {
    let version: String
    let downloadedAt: Date
}

let registry = FileSystemRegistryStore<CacheEntry>(
    directory: cacheURL,
    filename: "registry.json"
)

var entries = await registry.load()
entries["model-v1"] = CacheEntry(version: "1.0", downloadedAt: Date())
try await registry.save(entries)

Multi-Source Fallback Resolution

import PersistenceCore
import PersistenceKeychain
import PersistenceUserDefaults

let resolver = ChainedKeyResolver(
    secureStore: KeychainSecureStore(service: "com.example.myapp"),
    keyValueStore: UserDefaultsKeyValueStore(),
    keyMapping: [
        "API_KEY": .init(secure: "api_key", keyValue: "api_key"),
    ]
)

// Searches in order: Info.plist → Keychain → UserDefaults
let apiKey = await resolver.resolve("API_KEY")

InMemory Test Doubles

import PersistenceTesting

// Inject via DI in tests
let mockStore = InMemoryKeyValueStore()
let mockSecrets = InMemorySecureStore()
let mockDocs = InMemoryDocumentStore<Note>()

let settings = AppSettings(
    preferences: mockStore,
    secrets: mockSecrets,
    keyResolver: InMemoryKeyResolver(["API_KEY": "test-key"])
)

Architecture

2-layer architecture for separation of concerns:

Layer 0: PersistenceCore           Protocols + error types (no external dependencies)
Layer 1: PersistenceUserDefaults   UserDefaults concrete implementation
         PersistenceKeychain       Keychain concrete implementation
         PersistenceFileSystem     File system concrete implementation
         PersistenceTesting        InMemory test doubles

Requirements

  • iOS 17.0+ / macOS 14.0+
  • Swift 6.2+
  • Xcode 16.0+

License

MIT License - See LICENSE for details

Links

同じカテゴリの OSS — 通信 / サーバー

swift-api-client

Swift Package

async/await 対応の軽量 HTTP クライアント。型安全な API 通信を Swift で

Swift
· 通信 / サーバー
http-clientasync-awaitnetworking

swift-api-contract

Swift Package

Swift マクロで型安全な API 契約を定義する

Swift
· 通信 / サーバー
swift-macroapitype-safe

swift-api-server

Swift Package

Vapor を抽象化し、アプリケーションコードをフレームワーク実装から独立させるサーバー層

Swift
· 通信 / サーバー
servervaporbackend

swift-firebase-server

Swift Package

サーバーサイド Swift 向けの Firestore REST API クライアント

Swift
· 通信 / サーバー
firebasefirestoreserver

swift-http-transport

Swift Package

URLSession をプロトコル背後に隠し、リトライ / レート制限 / SSE を一元化する通信基盤

Swift
· 通信 / サーバー
httpurlsessionsse

© 2026 Kyoichi Taniguchi. All rights reserved.