💾 Safe, statically-typed, store-agnostic key-value storage written in Swift!

Overview

Storez 💾

Safe, statically-typed, store-agnostic key-value storage

Version Version Swift Platforms

Highlights

  • Fully Customizable:
    Customize the persistence store, the KeyType class, post-commit actions .. Make this framework yours!

  • Batteries Included:
    In case you just want to use stuff, the framework is shipped with pre-configured basic set of classes that you can just use.

  • Portability, Check!:
    If you're looking to share code between you app and extensions, watchkit, apple watch, you're covered! You can use the NSUserDefaults store, just set your shared container identifier as the suite name.

Example:

final class WeatherService {

  private enum Keys: Namespace {
    static let id = "weather-service"
    static let temperature = Key<Keys, Double>(id: "temp", defaultValue: 0.0)
  }

  private let store: UserDefaultsStore
  
  var temperature: Double {
    return store.get(Keys.temperature)
  }

  init(store: UserDefaultsStore) {
    self.store = store
  }

  func weatherUpdate(temperature: Double) {
    store.set(Keys.temperature, temperature)
  }
}

Features

Available Stores

Store Backend Subspec
UserDefaultsStore NSUserDefaults Storez/UserDefaults
CacheStore NSCache Storez/Cache

For all stores, simply use pod "Storez"

Type-safe, store-agnostic, nestable Key definitions

// Entries must belong to a "group", for namespacing
struct Animals: Namespace {
    static let id = "animals"
}

let kingdom = Key<Animals, Void?>(id: "mammals", defaultValue: nil)
kingdom.stringValue // "animals:mammals"

// Nesting
struct Cats: Namespace {
    typealias parent = Animals
    static let id = "cats"

    // Namespaces also have pre and post commit hooks
    func preCommitHook() { /* custom code */ }
    func postCommitHook() { /* custom code */ }
}

let cat = Key<Cats, Void?>(id: "lion", defaultValue: nil)
cat.stringValue // "animals:cats:lion"

Initialize the store you want

// Use UserDefaultsStore for this example
let store = UserDefaultsStore(suite: "io.kitz.testing")
let key = Key<GlobalNamespace, Int?>(id: "key", defaultValue: nil)

// With three simple functions
store.set(key, value: 8)
store.get(key) // 8
store.clear() // Start fresh every time for testing

Optionality is honored throughout

let nullable = Key<GlobalNamespace, String?>(id: "nullable", defaultValue: nil)
store.get(nullable)?.isEmpty   // nil
store.set(nullable, value: "")
store.get(nullable)?.isEmpty   // true

let nonnull = Key<GlobalNamespace, String>(id: "nonnull", defaultValue: "!")
store.get(nonnull).isEmpty  // false
store.set(nonnull, value: "")
store.get(nonnull).isEmpty  // true

Custom objects easily supported

NEW Simply conform to Codable!

(You can still use UserDefaultsConvirtable if needed)

struct CustomObject: Codable {
    var strings: [String]
}

// custom objects properly serialized/deserialized
let customObject = CustomObject(
    strings: ["fill", "in", "the"]
)

// let's add a processing block this time
let CustomValue = Key<GlobalNamespace, CustomObject?>(id: "custom", defaultValue: nil) {

    var processedValue = $0
    processedValue?.strings.append("blank!")
    return processedValue
}

store.set(CustomValue, value: customObject)
store.get(CustomValue)?.strings.joinWithSeparator(" ") // fill in the blank!

Make your own KeyType

// For example, make an key that emits NSNotifications
struct MyKey<G: Namespace, V>: KeyType {

    typealias NamespaceType = G
    typealias ValueType = V

    var stringValue: String
    var defaultValue: ValueType

    func didChange(oldValue: ValueType, newValue: ValueType) {
        NSNotificationCenter.defaultCenter().postNotificationName(stringValue, object: nil)
    }
}

Getting Started

Swift Package Manager

TODO: Write me

CocoaPods

CocoaPods is fully supported. You can choose which store you want to use (see above). Simply add the following line to your Podfile:

pod 'Storez/UserDefaults'

Motivation

I've seen a lot of great attempts at statically-types data stores, but they all build a tightly coupled design that limits the end-developer's freedom. With this framework, you can start prototyping right away with the shipped features, then replace the persistence store and KeyType functionality with your heart's content and keep your code the way it is!

Author

Mazyod (@Mazyod)

License

Storez is released under the MIT license. See LICENSE for details.

Comments
  • Get all of a kind

    Get all of a kind

    Hi there! How can I get all items stored under a certain Namespace? For example, I have the following namespace:

    struct ListsNamespace: Namespace {
        static let id = "lists"
    }
    

    and I want to fetch all 'List' items.

    Thanks!

    question 
    opened by nicolasalliaume 3
  • Cannot create Custom objects

    Cannot create Custom objects

    I try to create some custom objects,

    struct StorezArray {
        var arrStr: [String]
    }
    
    extension StorezArray: UserDefaultsConvertible {
        typealias UserDefaultsType = String
        
        var encodeForUserDefaults: StorezArray.UserDefaultsType? {
            return arrStr.joined(separator: ";")
        }
        
        static func decode(userDefaultsValue value: StorezArray.UserDefaultsType) -> StorezArray? {
            return self.init(arrStr: value.components(separatedBy: ";"))
        }
    }
    

    but xcode always says

    Type 'StorezArray' does not conform to protocol 'UserDefaultsConvertible'

    even though i add the protocol stub

    opened by aphe 2
  • clear() does not seem to clear user defaults

    clear() does not seem to clear user defaults

    The following code passes the first time. When the test is run a second time it fails.

    func testUserDefaultsBuggyClear() {
    
        var testStore = UserDefaultsStore(suite: "io.kitz.storez.test")
        let key = Key<GlobalNamespace, Int?>(id: "foo", defaultValue: nil)
    
        testStore.clear()
    
        XCTAssertNil(testStore.get(key))
        testStore.set(key, value: 666)
        XCTAssertEqual(testStore.get(key), 666)
    
        testStore.clear()
        XCTAssertNil(testStore.get(key))
    
        testStore = UserDefaultsStore(suite: "io.kitz.storez.test")
    
        XCTAssertNil(testStore.get(key))
    
        testStore.set(key, value: 666)
    }
    

    Run the following code several times and it eventually will always pass:

    func testUserDefaultsClear() {
    
        var testStore = UserDefaultsStore(suite: "io.kitz.storez.test")
        let key = Key<GlobalNamespace, Int?>(id: "foo", defaultValue: nil)
    
        testStore.clear()
    
        XCTAssertNil(testStore.get(key))
        testStore.set(key, value: 666)
        XCTAssertEqual(testStore.get(key), 666)
    
        testStore.clear()
        XCTAssertNil(testStore.get(key))
    
        testStore = UserDefaultsStore(suite: "io.kitz.storez.test")
    
        XCTAssertNil(testStore.get(key))
    
        testStore.set(key, value: 666)
    
        testStore.clear()
    }
    
    question 
    opened by maguro 2
  • the newest version build failed in carthage

    the newest version build failed in carthage

    build failed in carthage and when i build in Xcode i get the incurrent headers. the season is like this: The following build commands failed: Check dependencies (1 failure) ** BUILD FAILED **

    The following build commands failed: Check dependencies (1 failure) warning: no umbrella header found for target 'Storez-ios', module map will not be generated warning: no umbrella header found for target 'Storez-ios', module map will not be generated A shell task (/usr/bin/xcrun xcodebuild -workspace ~/Carthage/Checkouts/Storez/Storez.xcworkspace -scheme Storez-ios -configuration Release -sdk iphoneos ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES clean build) failed with exit code 65: --- xcodebuild: WARNING: Unable to open project file '~/Carthage/Checkouts/Storez/Playground/Playground.playground' in workspace '~/Carthage/Checkouts/Storez/Storez.xcworkspace'. ** CLEAN FAILED **

    bug 
    opened by strangeliu 2
  • Correct the spelling of CocoaPods in README

    Correct the spelling of CocoaPods in README

    This pull requests corrects the spelling of CocoaPods 🤓 https://github.com/CocoaPods/shared_resources/tree/master/media

    Created with cocoapods-readme.

    opened by ReadmeCritic 0
  • Cocoapods support

    Cocoapods support

    Probably makes sense to support Cocoapods using subspecs, so users can perhaps add support to Realm, SQLite, CoreData ... etc, without affecting light-weight stores.

    enhancement 
    opened by Mazyod 0
  • UserDefaults Migration

    UserDefaults Migration

    Add user defaults migration helper, which takes a list of of MigrationInfo. MigrationInfo is a struct that contains a KeyType to be migrated to, String which is the old key, and a processing block, that takes the old value and processes it to to return a new suitable value for KeyType.

    This is the actual use case that I have. I have simplified it so it makes more sense:

    old value: "CityId" -> "kw-city-asimah" new key: "general-settings:city" -> ""

    so, we can do this:

    let migrationInfo = MigrationInfo(
      keyType = Key<GeneralSettings, City>(id: "city", defaultValue: City.asimah),
      oldKey = "CityId",
      processor = { oldValue in
        // process from a string to a City type
        return mydb.getCity(oldValue)
    })
    
    enhancement 
    opened by Mazyod 1
Releases(v1.0.0)
  • v1.0.0(Dec 19, 2015)

    The library has been in private beta, and I only made it public after shipping it with my apps to the AppStore. You can rest assured it is battle tested.

    Source code(tar.gz)
    Source code(zip)
Owner
Kitz
Collection of quality Swift kits
Kitz
An Objective-C wrapper for RocksDB - A Persistent Key-Value Store for Flash and RAM Storage.

ObjectiveRocks ObjectiveRocks is an Objective-C wrapper of Facebook's RocksDB - A Persistent Key-Value Store for Flash and RAM Storage. Current RocksD

Iskandar Abudiab 56 Nov 5, 2022
An elegant, fast, thread-safe, multipurpose key-value storage, compatible with all Apple platforms.

KeyValueStorage An elegant, fast, thread-safe, multipurpose key-value storage, compatible with all Apple platforms. Supported Platforms iOS macOS watc

null 3 Aug 21, 2022
An efficient, small mobile key-value storage framework developed by WeChat. Works on Android, iOS, macOS, Windows, and POSIX.

中文版本请参看这里 MMKV is an efficient, small, easy-to-use mobile key-value storage framework used in the WeChat application. It's currently available on Andr

Tencent 15.4k Jan 6, 2023
CloudKit, Apple’s remote data storage service, provides a possibility to store app data using users’ iCloud accounts as a back-end storage service.

CloudKit, Apple’s remote data storage service, provides a possibility to store app data using users’ iCloud accounts as a back-end storage service. He

Yalantis 252 Nov 4, 2022
YapDB is a collection/key/value store with a plugin architecture. It's built atop sqlite, for Swift & objective-c developers.

YapDatabase is a collection/key/value store and so much more. It's built atop sqlite, for Swift & Objective-C developers, targeting macOS, iOS, tvOS &

Yap Studios 3.3k Dec 29, 2022
Key-Value store for Swift backed by LevelDB

SwiftStore Key/Value store for Swift backed by LevelDB. Usage Create instances of store import SwiftStore // Create a store. let store = SwiftStore(s

Hemanta Sapkota 119 Dec 21, 2022
A protocol-centric, type and queue safe key-value workflow.

Light-weight, strict protocol-first styled PropertyKit helps you to easily and safely handle guaranteed values, keys or types on various situations of

gitmerge 12 Feb 26, 2021
StorageManager - FileManager framework that handels Store, fetch, delete and update files in local storage

StorageManager - FileManager framework that handels Store, fetch, delete and update files in local storage. Requirements iOS 8.0+ / macOS 10.10+ / tvOS

Amr Salman 47 Nov 3, 2022
Add Strictly Typed NIO Channel Builders for Swift 5.7

⚠️ Requires Swift 5.7 Omnibus is a set of helpers for SwiftNIO that allow you to leverage Swift's generics type system to create NIO Channels. It depe

Orlandos 6 Jun 10, 2022
KeyPathKit is a library that provides the standard functions to manipulate data along with a call-syntax that relies on typed keypaths to make the call sites as short and clean as possible.

KeyPathKit Context Swift 4 has introduced a new type called KeyPath, with allows to access the properties of an object with a very nice syntax. For in

Vincent Pradeilles 406 Dec 25, 2022
Simple, Strongly Typed UserDefaults for iOS, macOS and tvOS

简体中文 DefaultsKit leverages Swift 4's powerful Codable capabilities to provide a Simple and Strongly Typed wrapper on top of UserDefaults. It uses less

Nuno Dias 1.4k Dec 26, 2022
Easiest local storage library in Swift

SundeedQLite SundeedQLite is the easiest offline database integration, built using Swift language Requirements iOS 12.0+ XCode 10.3+ Swift 5+ Installa

Nour Sandid 15 Sep 23, 2022
🛶Shallows is a generic abstraction layer over lightweight data storage and persistence.

Shallows Shallows is a generic abstraction layer over lightweight data storage and persistence. It provides a Storage<Key, Value> type, instances of w

Oleg Dreyman 620 Dec 3, 2022
Disk is a powerful and simple file management library built with Apple's iOS Data Storage Guidelines in mind

Disk is a powerful and simple file management library built with Apple's iOS Data Storage Guidelines in mind

Saoud Rizwan 3k Jan 3, 2023
Your Data Storage Troubleshooter 🛠

Your Data Storage Troubleshooter ?? Introduction StorageKit is a framework which reduces the complexity of managing a persistent layer. You can easily

StorageKit 231 Dec 29, 2022
pick the voice from the local storage.you can play and pause the voice

flutter_add_voice A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you starte

Mehrab Bozorgi 1 Nov 27, 2021
A CLI tool for the survey of the SSH-Key strength in your GitHub organization members.

GitHub organization SSH-keys checker A CLI tool for the survey of the SSH-Key strength in your GitHub organization members. Requirements macOS 12.0+ S

hugehoge 1 Dec 11, 2021
📕A single value proxy for NSUserDefaults, with clean API.

OneStore A single value proxy for NSUserDefaults, with clean API. With OneStore… Create one proxy(an OneStore object) for each NSUserDefaults value. M

Muukii 27 May 12, 2022
SQLite.swift - A type-safe, Swift-language layer over SQLite3.

SQLite.swift provides compile-time confidence in SQL statement syntax and intent.

Stephen Celis 8.7k Jan 3, 2023