💾 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
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 than 70 lines of code to acomplish this.

Nuno Dias 1.4k Dec 26, 2022
GenericLocalPersistence is a clean and easy-to-use code that is useful for integrating local storage

GenericLocalPersistence is a clean and easy-to-use code that is useful for integrating local storage like UserDefaults, PList, Keychain.

MindInventory 17 Sep 20, 2022
Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state.

Prephirences - Preϕrences Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, co

Eric Marchand 557 Nov 22, 2022
SwiftyUserDefaults - Modern Swift API for NSUserDefaults

SwiftyUserDefaults makes user defaults enjoyable to use by combining expressive Swifty API with the benefits of static typing. Define your keys in one place, use value types easily, and get extra safety and convenient compile-time checks for free.

Luke 4.7k Dec 27, 2022
tl;dr You love Swift's Codable protocol and use it everywhere

tl;dr You love Swift's Codable protocol and use it everywhere, who doesn't! Here is an easy and very light way to store and retrieve -reasonable amoun

Omar Albeik 452 Oct 17, 2022
Swift package to get the current user.

whoami.swift Retrieve the current user and environment through simple functions. This package can: Get the user's full name Get the user's username Ge

Nikita Rossik 0 Dec 29, 2021
💾 Safe, statically-typed, store-agnostic key-value storage written in Swift!

Storez ?? Safe, statically-typed, store-agnostic key-value storage Highlights Fully Customizable: Customize the persistence store, the KeyType class,

Kitz 67 Aug 7, 2022
Typed key-value storage solution to store Codable types in various persistence layers with few lines of code!

?? Stores A typed key-value storage solution to store Codable types in various persistence layers like User Defaults, File System, Core Data, Keychain

Omar Albeik 94 Dec 31, 2022
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
Modern thread-safe and type-safe key-value observing for Swift and Objective-C

Now Archived and Forked PMKVObserver will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork o

Postmates Inc. 708 Jun 29, 2022
RSA public/private key encryption, private key signing and public key verification in Swift using the Swift Package Manager. Works on iOS, macOS, and Linux (work in progress).

BlueRSA Swift cross-platform RSA wrapper library for RSA encryption and signing. Works on supported Apple platforms (using Security framework). Linux

Kitura 122 Dec 16, 2022
RSA public/private key encryption, private key signing and public key verification in Swift using the Swift Package Manager. Works on iOS, macOS, and Linux (work in progress).

BlueRSA Swift cross-platform RSA wrapper library for RSA encryption and signing. Works on supported Apple platforms (using Security framework). Linux

Kitura 122 Dec 16, 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
SwiftStore - Key/Value store for Swift backed by LevelDB.

SwiftStore Key/Value store for Swift backed by LevelDB. Usage Create instances of store import SwiftStore

Hemant Sapkota 119 Dec 21, 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 key value store for storing per-developer environment and application keys

A key value store for enviroment and application keys. Its good security practice to keep production keys out of developer hands. CocoaPods-keys makes

Orta Therox 1.5k Dec 20, 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