Code Monkey home page Code Monkey logo

storez's Introduction

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

You can add Storez to an Xcode project by adding it as a package dependency.

Depending on how your project is structured:

  • If you have a single application target that needs access to the library, then add Storez directly to your application.
  • If you want to use this library from multiple Xcode targets, or mixing Xcode targets and SPM targets, you likely want to create a shared framework that depends on Storez and then depend on that framework in all of your targets.

To use Storez in a Package.swift file, add this to the dependencies: section.

.package(url: "https://github.com/SwiftKitz/Storez.git", .upToNextMinor(from: "3.0.0")),

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.

storez's People

Contributors

haikusw avatar maryom avatar mazyod avatar readmecritic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

storez's Issues

Carthage Support

As simple as adding a tag with the Carthage support badge. Well, the readme should probably be updated as well.

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!

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

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

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

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.

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 **

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.