diff --git a/docs/Protocols.html b/docs/Protocols.html index 344e6c1..fb93469 100644 --- a/docs/Protocols.html +++ b/docs/Protocols.html @@ -17,7 +17,7 @@
-

Foil 5.0.0 Docs (100% documented)

+

Foil 5.0.1 Docs (100% documented)

GitHubView on GitHub

@@ -119,7 +119,7 @@

Declaration

diff --git a/docs/Protocols/UserDefaultsSerializable.html b/docs/Protocols/UserDefaultsSerializable.html index ded1869..96373b1 100644 --- a/docs/Protocols/UserDefaultsSerializable.html +++ b/docs/Protocols/UserDefaultsSerializable.html @@ -17,7 +17,7 @@
-

Foil 5.0.0 Docs (100% documented)

+

Foil 5.0.1 Docs (100% documented)

GitHubView on GitHub

@@ -198,7 +198,7 @@

Parameters

diff --git a/docs/Structs.html b/docs/Structs.html index e2eb044..4a66c62 100644 --- a/docs/Structs.html +++ b/docs/Structs.html @@ -17,7 +17,7 @@
-

Foil 5.0.0 Docs (100% documented)

+

Foil 5.0.1 Docs (100% documented)

GitHubView on GitHub

@@ -132,7 +132,7 @@

Declaration

diff --git a/docs/Structs/FoilDefaultStorage.html b/docs/Structs/FoilDefaultStorage.html index 86bfede..35aa75e 100644 --- a/docs/Structs/FoilDefaultStorage.html +++ b/docs/Structs/FoilDefaultStorage.html @@ -17,7 +17,7 @@
-

Foil 5.0.0 Docs (100% documented)

+

Foil 5.0.1 Docs (100% documented)

GitHubView on GitHub

@@ -232,7 +232,7 @@

Parameters

diff --git a/docs/Structs/FoilDefaultStorageOptional.html b/docs/Structs/FoilDefaultStorageOptional.html index 7eedb17..a1bfd20 100644 --- a/docs/Structs/FoilDefaultStorageOptional.html +++ b/docs/Structs/FoilDefaultStorageOptional.html @@ -17,7 +17,7 @@
-

Foil 5.0.0 Docs (100% documented)

+

Foil 5.0.1 Docs (100% documented)

GitHubView on GitHub

@@ -220,7 +220,7 @@

Parameters

diff --git a/docs/index.html b/docs/index.html index 04554b6..fce8484 100644 --- a/docs/index.html +++ b/docs/index.html @@ -16,7 +16,7 @@
-

Foil 5.0.0 Docs (100% documented)

+

Foil 5.0.1 Docs (100% documented)

GitHubView on GitHub

@@ -80,18 +80,18 @@

Why the name?

Usage

-

You can use @WrappedDefault for non-optional values and @WrappedDefaultOptional for optional ones. +

You can use @FoilDefaultStorage for non-optional values and @FoilDefaultStorageOptional for optional ones. You may wish to store all your user defaults in one place, however, that is not necessary. Any property on any type can use this wrapper.

final class AppSettings {
     static let shared = AppSettings()
 
-    @WrappedDefault(key: "flagEnabled")
+    @FoilDefaultStorage(key: "flagEnabled")
     var flagEnabled = true
 
-    @WrappedDefault(key: "totalCount")
+    @FoilDefaultStorage(key: "totalCount")
     var totalCount = 0
 
-    @WrappedDefaultOptional(key: "timestamp")
+    @FoilDefaultStorageOptional(key: "timestamp")
     var timestamp: Date?
 }
 
@@ -112,13 +112,13 @@ 

Using enum keys< case timestamp } -extension WrappedDefault { +extension FoilDefaultStorage { init(wrappedValue: T, _ key: AppSettingsKey) { self.init(wrappedValue: wrappedValue, key: key.rawValue) } } -extension WrappedDefaultOptional { +extension FoilDefaultStorageOptional { init(_ key: AppSettingsKey) { self.init(key: key.rawValue) } @@ -130,10 +130,10 @@

Observing changes

final class AppSettings: NSObject {
     static let shared = AppSettings()
 
-    @WrappedDefaultOptional(key: "userId")
+    @FoilDefaultStorageOptional(key: "userId")
     @objc dynamic var userId: String?
 
-    @WrappedDefaultOptional(key: "average")
+    @FoilDefaultStorageOptional(key: "average")
     var average: Double?
 }
 
@@ -169,9 +169,14 @@

Combine Alternative with K

Supported types

-

The following types are supported by default for use with @WrappedDefault.

+

The following types are supported by default for use with @FoilDefaultStorage.

+

[!NOTE] +While the UserDefaultsSerializable protocol defines a failable initializer, init?(storedValue:), it is possible to provide a custom implementation with a non-failable initializer, which still satisfies the protocol requirements.

+ +

For all of Swift’s built-in types (Bool, Int, Double, String, etc.), the default implementation of UserDefaultsSerializable is non-failable.

+

[!IMPORTANT] Adding support for custom types is possible by conforming to UserDefaultsSerializable. However, this is highly discouraged as all plist types are supported by default. UserDefaults is not intended for storing complex data structures and object graphs. You should probably be using a proper database (or serializing to disk via Codable) instead.

@@ -194,10 +199,11 @@

Supported types

  • RawRepresentable types
  • Codable types
  • +

    Notes on Codable types

    [!WARNING] -If you are storing custom Codable types and using the default implementation of UserDefaultsSerializable provided by Foil, then you must use the optional variant of the property wrapper, @WrappedDefaultOptional. This will allow you to make breaking changes to your Codable type (e.g., adding or removing a property). Alternatively, you can provide a custom implementation of Codable that supports migration, or provide a custom implementation of UserDefaultsSerializable that handles encoding/decoding failures. See the example below.

    +If you are storing custom Codable types and using the default implementation of UserDefaultsSerializable provided by Foil, then you must use the optional variant of the property wrapper, @FoilDefaultStorageOptional. This will allow you to make breaking changes to your Codable type (e.g., adding or removing a property). Alternatively, you can provide a custom implementation of Codable that supports migration, or provide a custom implementation of UserDefaultsSerializable that handles encoding/decoding failures. See the example below.

    Codable Example:

    @@ -208,14 +214,35 @@

    Supported types

    } // Yes, do this -@WrappedDefaultOptional(key: "user") +@FoilDefaultStorageOptional(key: "user") var user: User? // NO, do NOT this // This will crash if you change User by adding/removing properties -@WrappedDefault(key: "user") +@FoilDefaultStorage(key: "user") var user = User() +

    Notes on RawRepresentable types

    + +

    Using RawRepresentable types, especially as properties of a Codable type require special considerations. As mentioned above, Codable types must use @FoilDefaultStorageOptional out-of-the-box, unless you provide a custom implementation of UserDefaultsSerializable. The same is true for RawRepresentable types.

    + +
    +

    [!WARNING] +RawRepresentable types must use @FoilDefaultStorageOptional in case you modify the cases of your enum (or otherwise modify your RawRepresentable with a breaking change). Additionally, RawRepresentable types have a designated initializer that is failable, init?(rawValue:), and thus could return nil.

    + +

    Or, if you are storing a Codable type that has RawRepresentable properties, by default those properties should be optional to accommodate the optionality described above.

    +
    + +

    If you wish to avoid these edge cases with RawRepresentable types, you can provide a non-failable initializer:

    +
    extension MyStringEnum: UserDefaultsSerializable {
    +    // Default init provided by Foil
    +    // public init?(storedValue: RawValue.StoredValue) { ... }
    +
    +    // New, non-failable init using force-unwrap.
    +    // Only do this if you know you will not make breaking changes.
    +    public init(storedValue: String) { self.init(rawValue: storedValue)! }
    +}
    +

    Additional Resources