@@ -33,28 +33,7 @@ PersistentKeyValueKit is backed by a robust test suite.
3333
3434## Usage
3535
36- ### Types
37-
38- #### Primitive Types
39-
40- Primitive types are natively supported by ` UserDefaults ` and/or ` NSUbiquitousKeyValueStore ` . These types are all
41- ` KeyValuePersistible ` and are stored directly with no transformation (where possible). All other ` KeyValuePersistible `
42- types must be transformed into a primitive type through a ` PersistentKeyValueRepresentation ` .
43-
44- The primitive types are:
45-
46- - ` Bool `
47- - ` Data `
48- - ` Double `
49- - ` Float `
50- - ` Int `
51- - ` Optional `
52- - ` String `
53- - ` URL `
54- - ` [KeyValuePersisiblt] `
55- - ` [String: any KeyValuePersisitble] `
56-
57- #### Make a Type Persistible
36+ ### Make a Type Persistible
5837
5938Make a type persistible by conforming to ` KeyValuePersistible ` .
6039
@@ -64,37 +43,52 @@ Make a type persistible by conforming to `KeyValuePersistible`.
6443static var persistentKeyValueRepresentation: some PersistentKeyValueRepresentation<Self > { get }
6544```
6645
67- A representation is a type that describes how a value is persisted – how is is stored inside of ` UserDefaults ` or
68- ` NSUbiquitousKeyValueStore ` , and how it is retrieved. Severeal common representations are provided and it is easy to
46+ A representation is a type that describes how a value is persisted – how it is stored inside of ` UserDefaults ` or
47+ ` NSUbiquitousKeyValueStore ` , and how it is retrieved. Several common representations are provided and it is easy to
6948build custom ones inside of the ` KeyValuePersistible ` implementation.
7049
7150e.g.
7251
7352``` swift
7453extension UIContentSizeCategory : KeyValuePersistible {
75- public static var persistentKeyValueRepresentation: some PersistentKeyValueRepresentation<Self > {
54+ static var persistentKeyValueRepresentation: some PersistentKeyValueRepresentation<Self > {
7655 RawRepresentablePersistentKeyValueRepresentation ()
7756 }
7857}
7958```
8059
81- ##### Built-in Persistence Representations
60+ #### Primitive Types
61+
62+ Primitive types are natively supported by ` UserDefaults ` and/or ` NSUbiquitousKeyValueStore ` . These types are all
63+ ` KeyValuePersistible ` and are stored directly with little-to-no transformation. All other ` KeyValuePersistible `
64+ types must be transformed into a primitive type through a ` PersistentKeyValueRepresentation ` .
65+
66+ The primitive types are:
67+
68+ - ` Bool `
69+ - ` Data `
70+ - ` Double `
71+ - ` Float `
72+ - ` Int `
73+ - ` String `
74+ - ` URL `
75+ - ` Optional<T> where T: KeyValuePersistible `
76+ - ` [T] where T: KeyValuePersistible `
77+ - ` [String: T] where T: KeyValuePersistible `
78+
79+ ### Persistence Representations
8280
8381There are several built-in representations that cover the most common use cases for applications. They should be
8482generic enough for almost any need. They are all described here. Their building blocks are available if necessary, but
8583not described here.
8684
87- ###### ` ProxyPersistentKeyValueRepresentation `
85+ #### ` ProxyPersistentKeyValueRepresentation `
8886
8987` ProxyPersistentKeyValueRepresentation ` is a representation that persists a value as the ` Proxy ` type. The ` Proxy ` type
9088must be a ` KeyValuePersistible ` type.
9189
9290This is the base representation for types to build on top of. A common pattern is to use a primitive type as the proxy
93- type. Any ` KeyValuePersistible ` type can be used as the proxy type; there is no limit to the layers of indirection.
94-
95- > [ !WARNING]
96- > It is possible to define an infinite loop where ` KeyValuePersistible ` types proxy through each other recursively. This
97- > is a programming error and will result in undefined behavior at runtime.
91+ type, but any ` KeyValuePersistible ` type can be used as the proxy type. There is no limit to the layers of indirection.
9892
9993e.g.
10094
@@ -104,17 +98,17 @@ e.g.
10498extension Date : KeyValuePersistible {
10599 public static var persistentKeyValueRepresentation: some PersistentKeyValueRepresentation<Self > {
106100 ProxyPersistentKeyValueRepresentation (
107- to : \.timeIntervalSince1970 ,
108- from : Date.init (timeIntervalSince1970 : )
101+ to : \.timeIntervalSinceReferenceDate ,
102+ from : Date.init (timeIntervalSinceReferenceDate : )
109103 )
110104 }
111105}
112106```
113107
114- ###### ` RawRepresentablePersistentKeyValueRepresentation `
108+ #### ` RawRepresentablePersistentKeyValueRepresentation `
115109
116- ` RawRepresentablePersistentKeyValueRepresentation ` is a representation that persists a ` RawRepresentable ` value as its
117- ` RawValue ` , if ` RawValue ` is ` KeyValuePersistible ` .
110+ ` RawRepresentablePersistentKeyValueRepresentation ` is a proxy representation that persists a ` RawRepresentable ` value as
111+ its ` RawValue ` , if ` RawValue ` is ` KeyValuePersistible ` .
118112
119113e.g.
120114
@@ -134,69 +128,11 @@ extension RuntimeColorScheme: KeyValuePersistible {
134128}
135129```
136130
137- ###### ` StringlyKeyedDictionaryPersistentKeyValueRepresentation `
138-
139- ` StringlyKeyedDictionaryPersistentKeyValueRepresentation ` is a representation that persists a value as a
140- ` [String: Any] ` . This is just a typealias for ` ProxyPersistentKeyValueRepresentation<[String: Any]> ` .
141-
142- This representation is notable because ` [String: Any] ` is a primitive type and can be persisted directly with no
143- transformation. This is the most performant way to persist keyed types; much faster than JSON coding, for example. The
144- trade-off is that it requires manual (de)serialization.
145-
146- > [ !WARNING]
147- > ` Any ` is a lie: only property list types can be stored as values. Storing an unsupported type is a programming error
148- > and will result in a crash at runtime.
149-
150- e.g.
151-
152- ` Address ` is persisted as ` [String: Any] ` .
153-
154- ``` swift
155- struct Address {
156- let street: String
157- let city: String
158- let state: String
159- let zipCode: String
160- }
161-
162- extension Address : KeyValuePersistible {
163- static var persistentKeyValueRepresentation: some PersistentKeyValueRepresentation<Self > {
164- StringlyKeyedDictionaryKeyValueRepresentation {
165- [
166- " street" : $0 .street ,
167- " city" : $0 .city ,
168- " state" : $0 .state ,
169- " zipCode" : $0 .zipCode ,
170- ]
171- } from : {
172- guard
173- let street = $0 [" street" ] as? String ,
174- let city = $0 [" city" ] as? String ,
175- let state = $0 [" state" ] as? String ,
176- let zipCode = $0 [" zipCode" ] as? String
177- else {
178- return nil
179- }
180- return Address (street : street, city : city, state : state, zipCode : zipCode)
181- }
182- }
183- }
184- ```
185-
186- ###### ` CodablePersistentKeyValueRepresentation `
131+ #### ` CodablePersistentKeyValueRepresentation `
187132
188133` CodablePersistentKeyValueRepresentation ` is a proxy representation that persists a value as the ` Input ` /` Output ` type
189134of the given encoder and decoder.
190135
191- > [ !TIP]
192- > Although easy to use, ` CodablePersistentKeyValueRepresentation ` (with JSON) is the slowest built-in representation.
193- > One should prefer to use any other representation when possible. If one needs to persist a small keyed type, consider
194- > using ` ProxyPersistentKeyValueRepresentation ` with ` [String: Any] ` as the proxy type. ` [String: Any] ` is a primitive
195- > type and manual (de)serialization into a dictionary will be much faster.
196- >
197- > If one is storing a type that is so large as to be impractical to do manual (de)serialization, reconsider using
198- > ` UserDefaults ` or ` NSUbiquitousKeyValueStore ` altogether. They are not meant for large values.
199-
200136e.g.
201137
202138` Address ` is persisted as ` Data ` .
@@ -268,9 +204,8 @@ the amount of conditional code you need to write.
268204All key-based interfaces accept ` PersistentKeyProtocol ` , which both ` PersistentKey ` and ` PersistentDebugKey ` conform to.
269205
270206> [ !WARNING]
271- > Debug keys will only work if one is compiling this framework from source (e.g. as a SwiftPM dependency). If one is
272- > using a pre-built binary then the ` DEBUG ` code paths will likely not be included and default values will always be
273- > used.
207+ > Debug keys will only work if compiling this framework from source (e.g. as a SwiftPM dependency). If using a pre-built
208+ > binary then the ` DEBUG ` code paths will likely not be included and default values will always be used.
274209
275210e.g.
276211
@@ -293,12 +228,13 @@ userDefaults.get(.isAppStoreRatingEnabled) // false in Debug, true in Release
293228#### Use a Custom Representation for a Single Key
294229
295230Every ` KeyValuePersistible ` type has an associated ` PersistentKeyValueRepresentation ` type and
296- ` peristentKeyValueRepresentation ` property. This is the default representation used to persist the value into
297- the backing store.
231+ ` peristentKeyValueRepresentation ` property. This is the default representation used to persist the value with a store.
232+
233+ However, a representation for a single key can be provided at definition time—even if the value isn't
234+ ` KeyValuePersistible ` . This is useful for:
298235
299- However, you can supply a different representation for a single key at definition time. This is useful if you have
300- a type that you want to persist in a non-standard way, or if you have existing values that are stored differently
301- from the default representation.
236+ - One-off keys for nonconforming types.
237+ - Handling older values stored differently from the default representation.
302238
303239e.g.
304240
@@ -309,8 +245,8 @@ extension PersistentKeyProtocol where Self == PersistentKey<Date?> {
309245 " LastAppStoreReviewRequestDate" ,
310246 defaultValue : nil ,
311247 representation : ProxyPersistentKeyValueRepresentation (
312- to : \.timeIntervalSinceReferenceDate ,
313- from : Date.init (timeIntervalSinceReferenceDate : )
248+ to : \.timeIntervalSince1970 ,
249+ from : Date.init (timeIntervalSince1970 : )
314250 )
315251 )
316252 }
0 commit comments