Modern Swift API for NSUserDefaults

Overview

SwiftyUserDefaults

Platforms CI Status CocoaPods compatible Carthage compatible SPM compatible Swift version Swift version Swift version Swift version

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.

Previous versions' documentation: Version 4.0.0, Version 3.0.1
Migration guides: from 4.x to 5.x, from 4.0.0-alpha.1 to 4.0.0-alpha.3, from 3.x to 4.x

Version 5.0.0

FeaturesUsageCodableNSCodingRawRepresentableExtending existing typesCustom types

Property wrappersKVOdynamicMemberLookupLaunch argumentsUtilsInstallation

Features

There's only one step to start using SwiftyUserDefaults:

Define your keys!

extension DefaultsKeys {
    var username: DefaultsKey<String?> { .init("username") }
    var launchCount: DefaultsKey<Int> { .init("launchCount", defaultValue: 0) }
}

And just use it ;-)

// Get and set user defaults easily
let username = Defaults[\.username]
Defaults[\.hotkeyEnabled] = true

// Modify value types in place
Defaults[\.launchCount] += 1
Defaults[\.volume] -= 0.1
Defaults[\.strings] += "… can easily be extended!"

// Use and modify typed arrays
Defaults[\.libraries].append("SwiftyUserDefaults")
Defaults[\.libraries][0] += " 2.0"

// Easily work with custom serialized types
Defaults[\.color] = NSColor.white
Defaults[\.color]?.whiteComponent // => 1.0

If you use Swift 5.1 - good news! You can also use keyPath dynamicMemberLookup:

Defaults.color = NSColor.white

See more at the KeyPath dynamicMemberLookup section.

Usage

Define your keys

To get the most out of SwiftyUserDefaults, define your user defaults keys ahead of time:

let colorKey = DefaultsKey<String>("color", defaultValue: "")

Just create a DefaultsKey object, put the type of the value you want to store in angle brackets, the key name in parentheses, and you're good to go. If you want to have a non-optional value, just provide a defaultValue in the key (look at the example above).

You can now use the Defaults shortcut to access those values:

Defaults[key: colorKey] = "red"
Defaults[key: colorKey] // => "red", typed as String

The compiler won't let you set a wrong value type, and fetching conveniently returns String.

Take shortcuts

For extra convenience, define your keys by extending magic DefaultsKeys class and adding static properties:

extension DefaultsKeys {
    var username: DefaultsKey<String?> { .init("username") }
    var launchCount: DefaultsKey<Int> { .init("launchCount", defaultValue: 0) }
}

And use the shortcut dot syntax:

Defaults[\.username] = "joe"
Defaults[\.launchCount] += 1

Supported types

SwiftyUserDefaults supports all of the standard NSUserDefaults types, like strings, numbers, booleans, arrays and dictionaries.

Here's a full table of built-in single value defaults:

Single value Array
String [String]
Int [Int]
Double [Double]
Bool [Bool]
Data [Data]
Date [Date]
URL [URL]
[String: Any] [[String: Any]]

But that's not all!

Codable

Since version 4, SwiftyUserDefaults support Codable! Just conform to DefaultsSerializable in your type:

final class FrogCodable: Codable, DefaultsSerializable {
    let name: String
 }

No implementation needed! By doing this you will get an option to specify an optional DefaultsKey:

let frog = DefaultsKey<FrogCodable?>("frog")

Additionally, you've got an array support for free:

let froggies = DefaultsKey<[FrogCodable]?>("froggies")

NSCoding

NSCoding was supported before version 4, but in this version we take the support on another level. No need for custom subscripts anymore! Support your custom NSCoding type the same way as with Codable support:

final class FrogSerializable: NSObject, NSCoding, DefaultsSerializable { ... }

No implementation needed as well! By doing this you will get an option to specify an optional DefaultsKey:

let frog = DefaultsKey<FrogSerializable?>("frog")

Additionally, you've got an array support also for free:

let froggies = DefaultsKey<[FrogSerializable]?>("froggies")

RawRepresentable

And the last but not least, RawRepresentable support! Again, the same situation like with NSCoding and Codable:

enum BestFroggiesEnum: String, DefaultsSerializable {
    case Andy
    case Dandy
}

No implementation needed as well! By doing this you will get an option to specify an optional DefaultsKey:

let frog = DefaultsKey<BestFroggiesEnum?>("frog")

Additionally, you've got an array support also for free:

let froggies = DefaultsKey<[BestFroggiesEnum]?>("froggies")

Extending existing types

Let's say you want to extend a support UIColor or any other type that is NSCoding, Codable or RawRepresentable. Extending it to be SwiftyUserDefaults-friendly should be as easy as:

extension UIColor: DefaultsSerializable {}

If it's not, we have two options:
a) It's a custom type that we don't know how to serialize, in this case at Custom types
b) It's a bug and it should be supported, in this case please file an issue (+ you can use custom types method as a workaround in the meantime)

Custom types

If you want to add your own custom type that we don't support yet, we've got you covered. We use DefaultsBridges of many kinds to specify how you get/set values and arrays of values. When you look at DefaultsSerializable protocol, it expects two properties in each type: _defaults and _defaultsArray, where both are of type DefaultsBridge.

For instance, this is a bridge for single value data storing/retrieving using NSKeyedArchiver/NSKeyedUnarchiver:

public struct DefaultsKeyedArchiverBridge<T>: DefaultsBridge {

    public func get(key: String, userDefaults: UserDefaults) -> T? {
        userDefaults.data(forKey: key).flatMap(NSKeyedUnarchiver.unarchiveObject) as? T
    }

    public func save(key: String, value: T?, userDefaults: UserDefaults) {
        userDefaults.set(NSKeyedArchiver.archivedData(withRootObject: value), forKey: key)
    }

    public func deserialize(_ object: Any) -> T? {
        guard let data = object as? Data else { return nil }
        return NSKeyedUnarchiver.unarchiveObject(with: data) as? T
    }    
}

Bridge for default storing/retrieving array values:

public struct DefaultsArrayBridge<T: Collection>: DefaultsBridge {
    public func save(key: String, value: T?, userDefaults: UserDefaults) {
        userDefaults.set(value, forKey: key)
    }

    public func get(key: String, userDefaults: UserDefaults) -> T? {
        userDefaults.array(forKey: key) as? T
    }

    public func deserialize(_ object: Any) -> T? {
        nil
    }
}

Now, to use these bridges in our type we simply declare it as follows:

struct FrogCustomSerializable: DefaultsSerializable {

    static var _defaults: DefaultsKeyedArchiverBridge( { DefaultsKeyedArchiverBridge() }
    static var _defaultsArray: DefaultsKeyedArchiverBridge { DefaultsKeyedArchiverBridge() }

    let name: String
}

Unfortunately, if you find yourself in a situation where you need a custom bridge, you'll probably need to write your own:

final class DefaultsFrogBridge: DefaultsBridge {
    func get(key: String, userDefaults: UserDefaults) -> FrogCustomSerializable? {
        let name = userDefaults.string(forKey: key)
        return name.map(FrogCustomSerializable.init)
    }

    func save(key: String, value: FrogCustomSerializable?, userDefaults: UserDefaults) {
        userDefaults.set(value?.name, forKey: key)
    }

    func deserialize(_ object: Any) -> FrogCustomSerializable? {
        guard let name = object as? String else { return nil }

        return FrogCustomSerializable(name: name)
    }
}

final class DefaultsFrogArrayBridge: DefaultsBridge {
    func get(key: String, userDefaults: UserDefaults) -> [FrogCustomSerializable]? {
        userDefaults.array(forKey: key)?
            .compactMap { $0 as? String }
            .map(FrogCustomSerializable.init)
    }

    func save(key: String, value: [FrogCustomSerializable]?, userDefaults: UserDefaults) {
        let values = value?.map { $0.name }
        userDefaults.set(values, forKey: key)
    }

    func deserialize(_ object: Any) -> [FrogCustomSerializable]? {
        guard let names = object as? [String] else { return nil }

        return names.map(FrogCustomSerializable.init)
    }
}

struct FrogCustomSerializable: DefaultsSerializable, Equatable {

    static var _defaults: DefaultsFrogBridge { DefaultsFrogBridge() }
    static var _defaultsArray: DefaultsFrogArrayBridge { DefaultsFrogArrayBridge() }

    let name: String
}

To support existing types with different bridges, you can extend it similarly:

extension Data: DefaultsSerializable {
    public static var _defaultsArray: DefaultsArrayBridge<[T]> { DefaultsArrayBridge() }
    public static var _defaults: DefaultsDataBridge { DefaultsDataBridge() }
}

Also, take a look at our source code (or tests) to see more examples of bridges. If you find yourself confused with all these bridges, please create an issue and we will figure something out.

Property wrappers

SwiftyUserDefaults provides property wrappers for Swift 5.1! The property wrapper, @SwiftyUserDefault, provides an option to use it with key path and options: caching or observing.

Caching means that we will store the value for you and do not hit the UserDefaults for value almost never, only for the first value fetch.

Observing means we will observe, via KVO, your property so you don't have to worry if it was saved somewhere else and you use caching.

Now usage! Given keys:

extension DefaultsKeys {
    var userColorScheme: DefaultsKey<String> { .init("userColorScheme", defaultValue: "default") }
    var userThemeName: DefaultsKey<String?> { .init("userThemeName") }
    var userLastLoginDate: DefaultsKey<Date?> { .init("userLastLoginDate") }
}

You can declare a Settings struct:

struct Settings {
    @SwiftyUserDefault(keyPath: \.userColorScheme)
    var userColorScheme: String

    @SwiftyUserDefault(keyPath: \.userThemeName, options: .cached)
    var userThemeName: String?

    @SwiftyUserDefault(keyPath: \.userLastLoginDate, options: [.cached, .observed])
    var userLastLoginDate: Date?
}

KVO

KVO is supported for all the types that are DefaultsSerializable. However, if you have a custom type, it needs to have correctly defined bridges and serialization in them.

To observe a value for local DefaultsKey:

let nameKey = DefaultsKey<String>("name", defaultValue: "")
Defaults.observe(key: nameKey) { update in
	// here you can access `oldValue`/`newValue` and few other properties
}

To observe a value for a key defined in DefaultsKeys extension:

Defaults.observe(\.nameKey) { update in
	// here you can access `oldValue`/`newValue` and few other properties
}

By default we are using [.old, .new] options for observing, but you can provide your own:

Defaults.observe(key: nameKey, options: [.initial, .old, .new]) { _ in }

KeyPath dynamicMemberLookup

SwiftyUserDefaults makes KeyPath dynamicMemberLookup usable in Swift 5.1!

extension DefaultsKeys {
    var username: DefaultsKey<String?> { .init("username") }
    var launchCount: DefaultsKey<Int> { .init("launchCount", defaultValue: 0) }
}

And just use it ;-)

// Get and set user defaults easily
let username = Defaults.username
Defaults.hotkeyEnabled = true

// Modify value types in place
Defaults.launchCount += 1
Defaults.volume -= 0.1
Defaults.strings += "… can easily be extended!"

// Use and modify typed arrays
Defaults.libraries.append("SwiftyUserDefaults")
Defaults.libraries[0] += " 2.0"

// Easily work with custom serialized types
Defaults.color = NSColor.white
Defaults.color?.whiteComponent // => 1.0

Launch arguments

Do you like to customize your app/script/tests by UserDefaults? Now it's fully supported on our side, statically typed of course.

Note: for now we support only Bool, Double, Int, String values, but if you have any other requests for that feature, please open an issue or PR and we can talk about implementing it in new versions.

You can pass your arguments in your schema:

Pass launch arguments in Xcode Schema editor.

Or you can use launch arguments in XCUIApplication:

func testExample() {
    let app = XCUIApplication()
    app.launchArguments = ["-skipLogin", "true", "-loginTries", "3", "-lastGameTime", "61.3", "-nickname", "sunshinejr"]
    app.launch()
}

Or pass them as command line arguments!

./script -skipLogin true -loginTries 3 -lastGameTime 61.3 -nickname sunshinejr

Utils

Remove all keys

To reset user defaults, use removeAll method.

Defaults.removeAll()

Shared user defaults

If you're sharing your user defaults between different apps or an app and its extensions, you can use SwiftyUserDefaults by overriding the Defaults shortcut with your own. Just add in your app:

var Defaults = DefaultsAdapter<DefaultsKeys>(defaults: UserDefaults(suiteName: "com.my.app")!, keyStore: .init())

Check key

If you want to check if we've got a value for DefaultsKey:

let hasKey = Defaults.hasKey(\.skipLogin)

Installation

Requirements

Swift version >= 4.1
iOS version >= 9.0
macOS version >= 10.11
tvOS version >= 9.0
watchOS version >= 2.0

CocoaPods

If you're using CocoaPods, just add this line to your Podfile:

pod 'SwiftyUserDefaults', '~> 5.0'

Install by running this command in your terminal:

pod install

Then import the library in all files where you use it:

import SwiftyUserDefaults

Carthage

Just add to your Cartfile:

github "sunshinejr/SwiftyUserDefaults" ~> 5.0

Swift Package Manager

Just add to your Package.swift under dependencies:

let package = Package(
    name: "MyPackage",
    products: [...],
    dependencies: [
        .package(url: "https://github.com/sunshinejr/SwiftyUserDefaults.git", .upToNextMajor(from: "5.0.0"))
    ],
    targets: [...]
)

More like this

If you like SwiftyUserDefaults, check out SwiftyTimer, which applies the same swifty approach to NSTimer.

You might also be interested in my blog posts which explain the design process behind those libraries:

Contributing

If you have comments, complaints or ideas for improvements, feel free to open an issue or a pull request.

Authors and license

Maintainer: Łukasz Mróz

Created by: Radek Pietruszewski

SwiftyUserDefaults is available under the MIT license. See the LICENSE file for more info.

Comments
  • Allow default values to be read from any bundle or plist file

    Allow default values to be read from any bundle or plist file

    The NSUserDefaults class has a native function called registerDefaults that adds the contents of the specified dictionary to the registration domain. For extra convenience, you can use the extended version of registerDefaults to populate defaults values from your Settings.bundle or any plist file in your project.

    NSUserDefaults.registerDefaults("Settings.plist")
    NSUserDefaults.registerDefaults("Settings.plist", suiteName: "io.radex.SwiftyUserDefaults")
    NSUserDefaults.registerDefaults(bundleName: "Settings")
    NSUserDefaults.registerDefaults(bundle: NSBundle(forClass: self.dynamicType)) // used for unit testing
    

    To use an app group container for your NSUserDefault instance, use the optional suiteName parameter, or add a string entry called ApplicationGroupContainerIdentifier in your plist file.

    This pull request includes source code changes, unit tests, and updated readme documentation.

    This relates to #69, #51, and #59.

    opened by basememara 20
  • [Xcode 13.3] builtin extensions are missing

    [Xcode 13.3] builtin extensions are missing

    Problem

    struct SomeStruct: Codable, DefaultsSerializable {}
    => type 'SomeStruct' does not conform to protocol 'DefaultsSerializable'
    

    In Xcode 13.3, I can't build my apps about DefaultsSerializable.

    struct SomeStruct: Codable, DefaultsSerializable {
        public static var _defaults: DefaultsCodableBridge<SomeStruct> { .init() }
        public static var _defaultsArray: DefaultsCodableBridge<[SomeStruct]> { .init() }
    }
    => Build succeed
    

    Then I added some default extension's implementations. This problem is occurred about RowRepresentable, NSCoding, or more.

    WHY

    https://github.com/sunshinejr/SwiftyUserDefaults/blob/master/Sources/BuiltIns.swift extensions are missing?

    Xcode 13.3 Beta 1

    opened by shimastripe 14
  • Version 4.0.0

    Version 4.0.0

    Hey guys! Recently I've taken over the maintenance of SwiftyUserDefaults and I'm here to say that we are in the process of a big update. I started with the basics first:

    Currently I'm working on the newest version that should include few big changes:

    • Generic subscripts
    • Codable support
    • Custom default values
    • Protocol for custom getter/setter for given user default

    There are many more features that I would like to implement, but I just want to give you something as soon as possible. And I think that this is the core that you'll guys like (based on the feedback).

    It's not finished yet, but I'd expect to see a beta in the upcoming weeks. I will be also looking for options to get version for Swift 4.0/4.1 separately if possible, but conditional conformance from 4.1 might change things.

    Also @radex will be helping me in the first alpha phase to make sure we are on the right track. After that we will start a public beta so you could give us your feedback as well.

    I'll be updating the status of the release in this topic.

    Cheers! 🌞

    opened by sunshinejr 13
  • SwiftyUserDefaults.framework is invalid. The Info.plist file is missing the required key: CFBundleVersion.

    SwiftyUserDefaults.framework is invalid. The Info.plist file is missing the required key: CFBundleVersion.

    Hi guys

    Tried the latest release, commit github "radex/SwiftyUserDefaults" "f7878b0ae7b39dee85df6cf60b4d361af327e654", integrated via Carthage

    Getting this when uploading to AppStoreConnect, just FYI

    This bundle Payload/<myapp>.app/Frameworks/SwiftyUserDefaults.framework is invalid. The Info.plist file is missing the required key: CFBundleVersion.

    bug 
    opened by gabors 12
  • Add statically-defined default values WIP

    Add statically-defined default values WIP

    It implements the idea discussed in #51

    extension DefaultsKeys {
        static let username = DefaultsKey<String>("username", "default")
        static let launchCount = DefaultsKey<Int>("launchCount", 42)
    }
    

    Feedback is welcome :smiley:

    cc @radex @kaunteya @thellimist

    opened by delba 12
  • Memory leaks

    Memory leaks

    http://prntscr.com/ao2w98

    This repo has some memory leaks it seems. They weren't anything big in my project to care much about but some others might have problems. Its worth taking a look. I'm using Instruments in this ss

    opened by goktugyil 11
  • Using suiteName?

    Using suiteName?

    Awesome work, thx for sharing!

    I looked at the source code and read your blog post about it, but couldn't figure a good way to extend for optionally using suiteName. Do you have any suggestions for making this work with NSUserDefaults(suiteName: "my.storage.key")?

    It doesn't seem like it would be a trivial change because synchronize() would have to be called in every set, and also still allow to use NSUserDefaults.standardUserDefaults() optionally.

    I did something like this here, but I really like your API :). Maybe something like Defaults[SUITE_NAME_CONSTANT][.username]?

    opened by basememara 11
  • Support Swift value types

    Support Swift value types

    The official custom type support requires NSCoding, which rules out value types. Currently I’m working around this by using the legacy string API in a subscript extension and converting the value type to & from built-in codable types.

    It would be nice to have a better solution for this - support for RawRepresentable would cover a lot of cases, but having the ability to support arbitrary value types via some sort of codable type conversion protocol would be nicer.

    help wanted 
    opened by samritchie 10
  • Update 5.0.0 failed

    Update 5.0.0 failed

    Hi guys, I just updated to 5.0.0 and I face this issues: Ambiguous reference to member 'observe(_:options:handler:)' I can't observer change of a key path.

    opened by vienvu89 9
  • Storing nil in String? results in

    Storing nil in String? results in ""

    This is my definition, please note the Optional type:

    extension DefaultsKeys {
        static let myValue = DefaultsKey<String?>("myValue")
    }
    

    And this is how I'm storing my value:

    Defaults[.myValue] = newValue

    And this is me talking to llvm:

    (lldb) po newValue
    nil
    
    (lldb) po Defaults[.myValue]
    ▿ Optional<String>
      - some : ""
    

    Expected result: Defaults[.myValue] is nil Version: 4.0.0-alpha.1 Installed via CocoaPods

    opened by mvoelkl 9
  • SwiftyUserDefaults 5.0.0-beta.2 cause error on Xcode 11 SwiftUI Canvas

    SwiftyUserDefaults 5.0.0-beta.2 cause error on Xcode 11 SwiftUI Canvas

    I am using Xcode 11 GM Seed with SwiftyUserDefaults 5.0.0-beta.2, SwiftUI's canvas for previewing layout cause the following error. I also tired to downgrade SwiftyUserDefaults version to 4.0.0 and everything works fine.

    linker command failed with exit code 1 (use -v to see invocation)


    Failed to build the scheme "Testing": Link /Users/daniel/Library/Developer/Xcode/DerivedData/Testing-epcackvmcahjtubjqjwkhgqsrspu/Build/Intermediates.noindex/Previews/Testing/Products/Debug-iphonesimulator/libCwlCatchException.dylib: Undefined symbols for architecture x86_64: "_catchExceptionOfKind", referenced from: CwlCatchException.(catchReturnTypeConverter in 841BEC3F94220F0DFD4EA4E9DDB3DC93)(: A.Type, block: () -> ()) -> A? in CwlCatchException.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

    Link /Users/daniel/Library/Developer/Xcode/DerivedData/Testing-epcackvmcahjtubjqjwkhgqsrspu/Build/Intermediates.noindex/Previews/Testing/Products/Debug-iphonesimulator/libCwlPreconditionTesting.dylib: clang: error: no such file or directory: '/Users/daniel/Library/Developer/Xcode/DerivedData/Testing-epcackvmcahjtubjqjwkhgqsrspu/Build/Intermediates.noindex/Previews/Testing/Products/Debug-iphonesimulator/libCwlCatchException.dylib' Command Ld failed with a nonzero exit code

    opened by christinachanhk 8
  • [FYI] Defaults.observe might not work if it's shared

    [FYI] Defaults.observe might not work if it's shared

    Found this issue on internet. https://stackoverflow.com/questions/28736506/kvo-with-shared-nsuserdefaults-in-swift

    Just thought that it's worth sharing here. This can be closed as this is just for information. Cheers!

    opened by toshi0383 0
  • Looking for active maintainer.

    Looking for active maintainer.

    Hey all, as you might've noticed I didn't give the repository the love it deserves for quite some time. I was able to find maintainers for all the other projects I participated in, however I couldn't find anyone to actually take care of this one. If you think you'll do a good job taking care of SwiftyUserDefaults, please let me know!

    opened by sunshinejr 3
  • How to support [key:value] type with value:Codable,DefaultsSerializable

    How to support [key:value] type with value:Codable,DefaultsSerializable

    struct TestM: Codable,DefaultsSerializable{
        var name: String?
        var age: Int? = 0
    }
    
    extension DefaultsKeys{
        var tests: DefaultsKey<[String:[TestM]]>{.init("tests", defaultValue: [String:[TestM]]())}
    }
    
    let testM = TestM.init(name: "test", age: 18)
    Defaults[\.tests]["tests"] = [testM]
    
    opened by yanxiaobing 0
  • Xcode 13.x build error:'nil' requires a contextual type

    Xcode 13.x build error:'nil' requires a contextual type

    extension DefaultsKeys { var ABC_UserInfo: DefaultsKey<ABC_M?> { .init("ABC_Key", defaultValue: nil)} }

    struct ABC_M: HandyJSON, DefaultsSerializable, Codable { var id:UInt32? }

    on Xcode 13.x build error 'nil' requires a contextual type

    on other Xcode Version is Success

    opened by nanmingzhidian 0
  • Fix value upgraded from version 3

    Fix value upgraded from version 3

    Version 3 of SwiftyUserDefaults saved Array<String|Int|Float|Double...> as Array in UserDefaults, if upgrade it to version 4 or 5.x, the value will be saved as Codable. Then the values will be lost in the new version.

    opened by azone 2
Releases(5.3.0)
  • 5.3.0(Feb 24, 2021)

    Changelog

    • Renamed OptionalType.empty to OptionalType.__swifty_empty. Also removed the OptionalType.wrapped since it wasn't used in the framework anymore. Please note that this still shouldn't be something you rely on tho, we're gonna explore ways to remove the public OptionalType in a future releases. @sunshinejr
    Source code(tar.gz)
    Source code(zip)
  • 5.2.0(Feb 23, 2021)

    Changelog

    • DefaultsAdapter's subscript setters are now nonmutating. This shouldn't change much on the client side, but it does fix the issue with simultaneous access (#241, #247). @sunshinejr
    • Added DefaultsProviding protocol that DefaultsAdapter implements. It should help with DI and creating test adapters (#268). @sunshinejr
    Source code(tar.gz)
    Source code(zip)
  • 5.1.0(Jan 31, 2021)

    This version only increases the minimum requirements for iOS to make it compatible with Xcode 12. Redone since we didn't bump podspec version for CocoaPods support.

    Source code(tar.gz)
    Source code(zip)
  • 5.0.0(Dec 31, 2019)

    Finally version 5.0.0 is ready to go! After extensive testing we are releasing this version to the public. 🚀

    Very warm thank you to everyone participating in all these months of work: @marty-suzuki, @Z-JaDe, @philippec-ls and others that contributed to this project. On to the next year! 🥂

    Note: There shouldn't be any differences between latest beta and this version so you should be ready to go with bumping the version in your favorite dependency manager. If you are migrating from version 4 and lower, please check our migration guides.

    Source code(tar.gz)
    Source code(zip)
  • 5.0.0-beta.5(Oct 5, 2019)

    Unfortunately we had to remove Combine for now to keep Xcode 10 compatibility 😭 You might want to update to that version ASAP as it's fixing crashes on release builds...

    Changelog

    • Removed Combine extensions for now. Due to problems with weak-linking the framework, it's too difficult to support it with ease using all package managers and also without breaking backwards-compatibility. Probably gonna introduce it once we only support Xcode 11. @sunshinejr
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0-beta.4(Sep 27, 2019)

    Fixed a pretty bad indexing/building issue... See Migration Guide for more.

    Changelog

    • Fixed an issue with Xcode freezing, never-finishing indexing/building the project when we used Defaults[\.keyPath] in conditional statement. Unfortunately we had to add key label to Defaults[key: DefaultsKey<String?>...] where you wouldn't have to add the label to the subscript before. @sunshinejr.
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0-beta.3(Sep 25, 2019)

    Fixes to package managers! 🚀 Xcode 11 & Carthage are friends again. Also, you won't fetch testing libraries for SPM anymore so you can use your Xcode Previews again.

    Changelog

    • Fixed an issue with SPM integration - it no longer fetches testing libraries & doesn't create runtime crashes or Xcode Preview crashes anymore. @sunshinejr.
    • Fixed an issue where Carthage users using Xcode 11 couldn't install SwiftyUserDefaults 5. We added weak-linking for the xcodeproj so you might need additional steps for Xcode 10 + Carthage + SwiftyUserDefaults 5.* users. @sunshinejr.
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0-beta.2(Sep 9, 2019)

    This beta adds Combine support! Just use it on the DefaultsAdapter (if you can use Combine):

    func obserColorScheme() {
        colorSchemeObserver = Defaults.publisher(for: \.colorSchemeObserver)
            .sink { value in
                //
            }
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0-beta.1(Sep 6, 2019)

    This cool release prepares for Swift 5.1 - we introduce key path access (enabling dynamicMemberLookup) and property wrapper! Additionally there are some changes to all Defaults global variable, DefaultsKeys and `DefaultsBridge - check out our migration guide for more.

    Changelog

    • Introduced DefaultsAdapter thats the main object for user defaults and the Defaults global variable. @marty-suzuki
    • Thanks to DefaultsAdapter, if you are using Swift 5.1 you can use dyanmic member lookup! This allows you to use Defaults.yourKey instead of Defaults[.yourKey]. In case you are not using Swift 5.1, you would need to transition to Defaults[\.yourKey] instead of Defaults[.yourKey]. @marty-suzuki
    • There is a new protocol, DefaultsKeyStore that DefaultsKeys conform to. This key store is then accepted by the DefaultsAdapter so you can have multiple key stores for multiple adapters! @marty-suzuki
    • Unfortunately the above means that you need to declare your keys as a computed properties instead of static stored ones.@marty-suzuki
    • DefaultsBridge is now a struct, not a class. You need to use composition instead of inheritance to compose them. @Z-JaDe
    • DefaultsBridge changed a little bit, there is no isSerialized property anymore, if you create your own bridge you need to provide deserialize() method as well. @Z-JaDe
    • Added @SwiftyUserDefault property wrapper for Swift 5.1 users! It uses key paths and has options to cache/observe your defaults as well. @sunshinejr
    • Updated project to recommended settings of Xcode 10.2. @philippec-ls
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0(Apr 26, 2019)

  • 4.0.0-beta.2(Mar 9, 2019)

    Minor stability update for Carthage users. This should fix the linking problem we've had in beta.1. No other fixes/updates were introduced in here.

    Source code(tar.gz)
    Source code(zip)
  • 4.0.0-beta.1(Feb 25, 2019)

    This update introduces few cool additions to the library! 🎉

    Changelog

    • Added support for launch arguments/plist for Bool, Double, Int, String values. @sunshinejr
    • Added support for KVO! DivineDominion, toshi0383, @sunshinejr
    • Brought back dictionary support for [String: Any]/[String: String] and corresponding array version of it [[String: Any]]/[[String: String]]. @sunshinejr

    If you have already created a custom bridge for you type, and you want to use it with KVO, you'll need to override two new functions: isSerialized() and deserialize(_:). See Readme for more instructions.

    Source code(tar.gz)
    Source code(zip)
  • 4.0.0-alpha.3(Feb 19, 2019)

  • 4.0.0-alpha.2(Feb 18, 2019)

    🎉🎉🎉

    We're back with alpha 2!

    Migration guide from 3.x to 4.x Migration guide from 4.0.0-alpha.1 to 4.0.0-alpha.2

    Changelog

    • Swift 4.2 support. @sunshinejr
    • Early Swift 5.0 support! @sunshinejr
    • Rewritten core. We use DefaultsBridges now to define getters/setters for given type. @sunshinejr
    • Fixed a bug where you couldn't extend non-final class like NSColor. @sunshinejr
    • Removed type-based default values. This means you need to use key-based defaultValue or use an optional DefaultsKey from now on. @sunshinejr
    • Improved CI infra: Swift 4.1/4.2/5.0 builds with CocoaPods/Carthage/SPM integration scripts. @sunshinejr
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0-alpha.1(May 8, 2018)

    🎉🎉🎉

    This is a huge release. Please try it out and let me know how it feels as we still have time for improvements!

    Migration guide from 3.x to 4.x

    Changelog

    • Swift 4.1 support @sunshinejr
    • Added Codable support! @sunshinejr
    • Added generic subscripts support (better DefaultsKey init diagnostics and accessing Defaults[.key]) @sunshinejr
    • Added default values protocols (DefaultsDefaultValueType, DefaultsDefaultArrayValueType) - this means that you can extend any type with default value so you can create non-optional DefaultsKey afterwards! @sunshinejr
    • Added default values in DefaultsKey, e.g. DefaultsKey<String>("test", defaultValue: "default value") @sunshinejr
    • Added better support for custom types: using DefaultsSerializable, when your type implements NSCoding, RawRepresentable (enums as well) or Codable, you get default implementations for free! @sunshinejr
    • Added automatic array support for any type that is available to SwiftyUserDefaults (means custom with DefaultsSerializable as well!) @sunshinejr
    • Added Swift Package Manager support! @sunshinejr
    • Added [URL] built-in support! @sunshinejr
    • A lot of infrastructure changes (CI, project), around 350 tests to make sure all of the changes work properly! @sunshinejr
    • Removed legacy strings based API (Defaults["test"]), Dictionary and Any support (sorry, with all the changes in the library we had to, but you probably can bring it back with DefaultsSerializable anyways 😅) @sunshinejr
    Source code(tar.gz)
    Source code(zip)
📕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
TypedDefaults is a utility library to type-safely use NSUserDefaults.

TypedDefaults TypedDefaults is a utility library to type-safely use NSUserDefaults. Motivation The talk Keep Calm and Type Erase On by Gwendolyn Westo

Kazunobu Tasaka 110 Feb 6, 2022
A lightweight wrapper over UserDefaults/NSUserDefaults with an additional layer of AES-256 encryption

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

Victor Peschenkov 216 Dec 22, 2022
Save NSObject into NSUserDefaults in one-line, auto class mapping

Akaibu What is it ? Archive any class in just ONE-LINE of code. Automatically map class's properties under the hood. Drop in replacement of NSObject S

Roy Tang 16 Jun 21, 2021
NSUserDefaults with Wings!

#Palau: NSUserDefaults with Wings! Features | Included Types | Installation | Validators and Defaults | Custom Types | DidSet Callback | ------- Featu

symentis GmbH 387 Jun 29, 2022
Modern interface to UserDefaults + Codable support

Default Modern interface to UserDefaults + Codable support What is Default? Default is a library that extends what UserDefaults can do by providing ex

Nicholas Maccharoli 475 Dec 20, 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 Dec 31, 2022
A demo app to showcase pixel perfect, modern iOS development with SwiftUI and Combine on MVVM-C architecture.

Pixel_Perfect_SwiftUI A demo app to showcase pixel perfect, modern iOS development with SwiftUI and Combine on MVVM-C architecture. Tech Stack: Swift,

Burhan Aras 0 Jan 9, 2022
How to use the Zeit Online Content API with Swift 4

ZeitSuche_iOS Version 1.4.0 - September 12, 2018 This iOS app (iPhone) shows how to use the Zeit Online Content API with Swift 4. To test this app you

Bodo Schönfeld 3 Dec 7, 2022
This Project domonstrate the latest Swift on Server to create RESTFul API's connected via Database: MongoDB NoSql

Swift is a general-purpose programming language built using a modern approach to safety & performance that make it specifically suitable for Server applications. Vapor is a web framework for Swift, allowing you to write backends, web apps APIs and HTTP servers in Swift

Furqan 3 Aug 23, 2022
A basic application that fetches crypto coin datas from CoinBase API.

HW5_ErincDokumacioglu App named Investor that fetches latest exchange rates for cryptocurrencies from CoinMarketCap Currently has some issues, mainly

Erinç Olkan Dokumacıoğlu 0 Oct 30, 2021
BucketServer - Small API with SQLite database that saves notes for an iOS appliction called Bucket list

BucketList Server-Side Small API with SQLite database that saves notes for an iO

null 0 Dec 30, 2021
A Swifty API for global macOS hotkeys.

A Swifty API for global macOS hotkeys. Install Add the following dependency to your Package.swift file: .package(url: "https://github.com/jordanbaird/

Jordan Baird 9 Dec 28, 2022
A fast, pure swift MongoDB driver based on Swift NIO built for Server Side Swift

A fast, pure swift MongoDB driver based on Swift NIO built for Server Side Swift. It features a great API and a battle-tested core. Supporting both MongoDB in server and embedded environments.

null 646 Dec 10, 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
🧡 SQLiteOrm-Swift is an ORM library for SQLite3 built with Swift 5

?? Easy to use SQLite ORM library written with Swift

Yevgeniy Zakharov 25 Oct 6, 2022
ObjectBox Swift - persisting your Swift objects superfast and simple

ObjectBox Swift ObjectBox is a superfast, light-weight object persistence framework. This Swift API seamlessly persists objects on-device for iOS and

ObjectBox 380 Dec 19, 2022
Shows the issue with swift using an ObjC class which has a property from a swift package.

SwiftObjCSwiftTest Shows the issue with swift using an ObjC class which has a property from a swift package. The Swift class (created as @objc derived

Scott Little 0 Nov 8, 2021