Simple, Strongly Typed UserDefaults for iOS, macOS and tvOS

Overview

DefaultsKit

cocoapods compatible carthage compatible language swift

简体中文

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.

Installation >> instructions <<

Usage

Instantiate, or get a shared instance of Defaults

let defaults = Defaults() // or Defaults.shared

Then:

// Define a key
let key = Key<String>("someKey")

// Set a value
defaults.set("Codable FTW 😃", for: key)

// Read the value back
defaults.get(for: key) // Output: Codable FTW 😃

Check if a key has a value:

if defaults.has(key) { 
    // Do your thing
}

If you just need to know that a key/value pair exists, without actually using the value, use the has() method instead of the optional get(for:key). For complex objects it will prevent any unnecessary deserialization.

Implicit Member Expression

You can find a convenience wrapper for your keys by extending DefaultsKey. This allows you use Implicit Member Expression:

// Extend with a custom key
extension DefaultsKey {
    static let someKey = Key<String>("someKey")
}

// Then use it like this
defaults.set("Some key", for: .someKey)
defaults.get(for: .someKey) // Output: Some key

Complex objects

To store a complex object just conform to the Codable protocol:

struct Person: Codable {
    let name: String
    let age: Int
}

Then:

// Create a key
let key = Key<Person>("personKey")

// Get an instance of your Codable conforming enum, struct or class
let person = Person(name: "Bonnie Greenwell", age: 80)

// Set the value
defaults.set(person, for: key)

And finally:

// Read it back
let person = defaults.get(for: key)
person?.name // Bonnie Greenwell
person?.age  // 80

Nested Objects

You can also use nested objects as long as they conform to the Codable protocol:

enum Pet: String, Codable {
    case cat
    case dog
}

struct Person: Codable {
    let name: String
    let pets: [Pet]
}

// Get a Codable conforming instante
let person = Person(name: "Claire", pets: [.cat])

// Set the value
defaults.set(person, for: key)

// And read it back
let person = defaults.get(for: key)
person?.name        // Claire
person?.pets.first  // cat

License

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

Help Wanted

Review/Translate README.zh-CN.md to Chinese

Chinese is the #1 spoken language in the world and I'd love to have DefaultsKit be more inclusive, unfortunately I don't speak Chinese. If you know chinese, and would like to help out, please see issue #1

Thank you 🙏

Comments
  • Translate README to Chinese

    Translate README to Chinese

    Create a README.CN.md in Chinese.

    Chinese is the #1 spoken language in the world and I'd love to have DefaultsKit be more inclusive, unfortunately I don't speak Chinese. If you know Chinese, and would like to help out, I'd be eternally grateful.

    Thank you 🙏

    help wanted 
    opened by nmdias 8
  • Missing DefaultsKey

    Missing DefaultsKey

    Testing out the repo, looks great! Of course, immediately set out to create default keys, as that just feels right. Noted the Defaults.swift file is missing (that is in the demo). ps: naming the file to match only makes sense too ;)

    Cheers!

    opened by wdcurry 6
  • Using PLIST encoder for defaults

    Using PLIST encoder for defaults

    Hi!

    Great idea/framework. Can't wait to use Codable everywhere in my projects.

    Looked over the code and thought of something.

    • Why are you using JSONEncoder/Decoder? Since you are storing un UserDefaults, you are converting to JSON data then storing. BUT UserDefaults is a PLIST, so it accepts any value that is a PLIST. You could convert the model you want to save with the PLIST decoder/encoder and not worry about changing back and forth from Data.

    Maybe both could be an option. Just curious. 👍

    opened by danlozano 5
  • How to read it out from different View Controller?

    How to read it out from different View Controller?

    Dears:

    I don't know how to read it back at different view controllers. For example: I save my data at login view controller, and I need to read it out at Friends View Controller. How do I do? Thanks!

    opened by chingyu01 4
  • Redundant conformance constraint

    Redundant conformance constraint

    Great library!

    I am trying to write a small wrapper and am running into a compiler warning Redundant conformance constraint. I'm newer to generics but was hoping for some direction what I'm doing wrong. Thanks!

    screen shot 2017-10-12 at 1 05 16 pm
    opened by kmcgill88 4
  • Add ability to save dates

    Add ability to save dates

    While working with this I noticed I could not save Date's which is a requirement of mine. In the past I've done this the old fashion way:

    UserDefaults.standard.set(Date(), forKey: SHOULD_REFRESH)
    UserDefaults.standard.synchronize()
    

    I'm not sure if isPrimitive name still fits but thought I'd leave that up to you. I'd love to use DefaultsKit with Date's. Please consider my PR.

    Thanks!

    opened by kmcgill88 3
  • why type of Key class must be generic?

    why type of Key class must be generic?

    We have to define generic type of every Key instance but I do not get it.

    first parameter of 'save' method 'value' already knows what generic type is gonna be saved.

    Is it possible to improve Key class which is gonna not be required to define what generic type is?

    What I mean:

    let object = Person(n: "Mustafa")
    
    Defaults.shared.set(object, Key("admin")
    

    we can get the type of object variable.

    opened by muhasturk 2
  • How to extend Key class Key with keys?

    How to extend Key class Key with keys?

    Hello,

    Awesome Library!!!

    I am trying for the below things:

    My Goal defaults.set(true, forKey: .isUserLoggedIn)

    Currently I'm doing in this way:

    enum Keys {
        static let isUserLoggedIn = Key<Bool>("isUserLoggedIn")
    }
    
    defaults.set(true, forKey: Keys.isUserLoggedIn)
    

    Please guide me.

    opened by toseefkhilji 2
  • Remove use of synchronize()

    Remove use of synchronize()

    https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes/foundation_release_notes

    also this

    https://twitter.com/catfish_man/status/674727133017587712

    :)

    opened by heumn 1
  • Swift.EncodingError.Context(codingPath: [], debugDescription:

    Swift.EncodingError.Context(codingPath: [], debugDescription: "Top-level Data encoded as string JSON fragment.", underlyingError: nil)

    This was an accident when I converted the custom model using an archive to binary using "Defaults" for storage. This is a problem I recently used with Xcode 9.4.1, Swift 4.0. I didn't see this problem before using Xcode 9.2. The version of Defaults that I am using now is 0.0.8.

    I also looked at this document "https://git.snooey.net/Mirrors/swift/blob/a8ba0772cd2f887c2b48549172d2c447140e06d8/stdlib/public/SDK/Foundation/JSONEncoder.swift" I don't quite understand why this error caused my storage binary type to fail.

    I hope you can help me.

    Thanks

    opened by niuxinhuai 1
  • Enable store RawRepresentable directly

    Enable store RawRepresentable directly

    I need to store enum and optionSet in DefaultsKit without writing duplicated code

    After add these two extension methods. Any RawRepresentable can be get and set directly.

    public func get<ValueType: RawRepresentable>(for key: Key<ValueType>) -> ValueType? where ValueType.RawValue: Codable
    public func set<ValueType: RawRepresentable>(_ value: ValueType, for key: Key<ValueType>) where ValueType.RawValue: Codable
    
    opened by wddwycc 1
  • how to initialise default with suitname ?

    how to initialise default with suitname ?

    I have App where I use custom keyboard extension and I want to share default with group identifires for that I need to initialise default with suit name how can we do this with DefaultsKit ?

    opened by dipenshivlab 0
  • Xcode 12.0.1 & SPM

    Xcode 12.0.1 & SPM

    I get this error when I try to install DefaultsKit with SPM (Carthage works)

    because every version of DefaultsKit contains incompatible tools version and root depends on DefaultsKit 0.2.0, version solving failed.

    opened by norbdev 3
  • Test has function on simulator iOS10.3.1 always true

    Test has function on simulator iOS10.3.1 always true

    First thanks for sharing this useful frame.

    My problem is when I use Xcode 11.5 simulator iOS 10.3.1 test Defaults.shared.has(.userIdKey) function (.userIdKey is String type) after I use clear the value, it's always return true. But when I use Defaults.shared.get(for: .userIdKey) is nil.

    So I debug has function source code "po userDefaults.value(forKey: key._key)" is ▿ Optional

    • some : <62706c69 73743030 d4010203 04050608 09582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f701200 0186a0a1 0755246e 756c6c5f 100f4e53 4b657965 64417263 68697665 72d10a0b 54726f6f 74800008 111a232d 3237393f 51545900 00000000 00010100 00000000 00000c00 00000000 00000000 00000000 00005b>

    (lldb) po userDefaults.object(forKey: key._key) ▿ Optional

    • some : <62706c69 73743030 d4010203 04050608 09582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f701200 0186a0a1 0755246e 756c6c5f 100f4e53 4b657965 64417263 68697665 72d10a0b 54726f6f 74800008 111a232d 3237393f 51545900 00000000 00010100 00000000 00000c00 00000000 00000000 00000000 00005b>

    I test same code on iOS 11.4, iOS12, iOS13 on simulator are all correct.

    I don't know what's make this issue. I have no real machine with version 10.3.1 to test it.

    At last I use userDefaults.string(forKey: key._key) test it is correct, It seems userDefaults.value have problem on iOS 10.3.1 version.

    May be public func has(_ key: Key) we can get value type first, then use match function get value is better.

    opened by luffyjie 0
Owner
Nuno Dias
Nuno Dias
Zephyr synchronizes specific keys and/or all of your UserDefaults over iCloud using NSUbiquitousKeyValueStore.

Zephyr ??️ Effortlessly sync UserDefaults over iCloud About Zephyr synchronizes specific keys and/or all of your UserDefaults over iCloud using NSUbiq

Arthur Ariel Sabintsev 845 Jan 6, 2023
Default is a Modern interface to UserDefaults + Codable support

Default is a library that extends what UserDefaults can do by providing extensions for saving custom objects that conform to Codable and also providing a new interface to UserDefaults described below, via the protocol DefaultStorable. You can use only the Codable support extensions or the DefaultStorable protocol extensions or both. (or none, that's cool too)

Nicholas Maccharoli 475 Dec 20, 2022
SecureDefaults is a wrapper over UserDefaults/NSUserDefaults with an extra AES-256 encryption layer

SecureDefaults for iOS, macOS Requirements • Usage • Installation • Contributing • Acknowledgments • Contributing • Author • License SecureDefaults is

Victor Peschenkov 216 Dec 22, 2022
💾 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
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
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
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
An iOS Safari extension that redirects MetaMask calls to Rainbow.

Rainbow Bridge (iOS App) An iOS Safari extension that redirects MetaMask calls to Rainbow. Since I can't figure out how to get the Rainbow source runn

Miguel Piedrafita 10 Aug 20, 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
A result builder that build HTML parser and transform HTML elements to strongly-typed result, inspired by RegexBuilder.

HTMLParserBuilder A result builder that build HTML parser and transform HTML elements to strongly-typed result, inspired by RegexBuilder. Note: Captur

null 4 Aug 25, 2022
📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.

Apollo iOS is a strongly-typed, caching GraphQL client, written in Swift. It allows you to execute queries and mutations against a GraphQL server, and

Apollo GraphQL 3.6k Jan 7, 2023
Pilgrim - Dependency injection for Swift (iOS, OSX, Linux). Strongly typed, pure Swift successor to Typhoon.

pilgrim.ph Pilgrim is a dependency injection library for Swift with the following features: Minimal runtime-only library that works with pure Swift (s

AppsQuick.ly 60 Oct 24, 2022
PMJSON provides a pure-Swift strongly-typed JSON encoder/decoder

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

Postmates Inc. 364 Sep 28, 2022
Lazily deserialize JSON into strongly typed Swift objects

LazyObject Lazily deserialize JSON into strongly typed Swift objects, with a few getter style options. Is your app using it? Let me know! Installation

rob phillips 11 Nov 16, 2022
Meet Corvus, the first strongly declarative server-side framework.

Corvus Corvus is the first truly declarative server-side framework for Swift. It provides a declarative, composable syntax which makes it easy to get

null 42 Jun 29, 2022
Meet Corvus, the first strongly declarative server-side framework.

Corvus Corvus is the first truly declarative server-side framework for Swift. It provides a declarative, composable syntax which makes it easy to get

null 42 Jun 29, 2022
In this mini app covered the concepts like basics of SwiftUI and Navigations and Animations and List with CRUD functions and MVVM and App Launch and App icons adding and also applied persistence using UserDefaults Concept.

TodoList In this application used the concepts from the beginner level project of SwiftUI_Evolve_1 The following concepts covered in this mini app Swi

Sivaram Yadav 2 Dec 4, 2021
IHTypeWriterLabel - A simple, UILabel subclass which poulates itself as if being typed

IHTypeWriterLabel A simple, UILabel subclass which poulates itself as if being typed. HighLights Written purely in SWIFT. Very simple and lightweight.

Md Ibrahim Hassan 24 May 7, 2019
Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state. UserDefaults

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
Swifty and modern UserDefaults

Defaults Swifty and modern UserDefaults Store key-value pairs persistently across launches of your app. It uses NSUserDefaults underneath but exposes

Sindre Sorhus 1.3k Jan 6, 2023