Skip to content

Instantly share code, notes, and snippets.

@rubencodes
Created December 1, 2022 21:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rubencodes/6ace9948102da2905b9d260749c39a97 to your computer and use it in GitHub Desktop.
Save rubencodes/6ace9948102da2905b9d260749c39a97 to your computer and use it in GitHub Desktop.
Property wrapper for storing any `Codable` data structure into a `UserDefaults` store.
import SwiftUI
@propertyWrapper public struct DataStorage<Value: Codable>: DynamicProperty {
// MARK: - Private Properties
private var defaultValue: Value
private var storageKey: String
private var store: UserDefaults
private var data: AppStorage<Data?>
// MARK: - Internal Properties
public var wrappedValue: Value {
get {
guard
let data = data.wrappedValue,
let value = try? JSONDecoder().decode(Value.self, from: data) as Value else {
return defaultValue
}
return value
}
nonmutating set {
guard let data = try? JSONEncoder().encode(newValue) else {
return
}
self.store.set(data, forKey: self.storageKey)
self.data.wrappedValue = data
}
}
public var projectedValue: Binding<Value> {
Binding<Value>(get: { self.wrappedValue },
set: { newValue in self.wrappedValue = newValue })
}
// MARK: - Lifecycle
/// Property wrapper for storing any `Codable` data structure into a `UserDefaults` store.
///
/// Example usage:
/// ```
/// @DataStorage("todoList", store: .standard) private var todos: [String] = []
/// ```
public init(wrappedValue: Value, _ storageKey: String, store: UserDefaults = .standard) {
defaultValue = wrappedValue
self.storageKey = storageKey
self.store = store
data = AppStorage(storageKey, store: store)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment