Skip to content

Instantly share code, notes, and snippets.

@jakehawken
Last active July 12, 2023 20:27
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 jakehawken/63acdfc8c7caac4064700ba097240377 to your computer and use it in GitHub Desktop.
Save jakehawken/63acdfc8c7caac4064700ba097240377 to your computer and use it in GitHub Desktop.
@DiskBacked - Easy computed properties backed by UserDefaults.
/// This propety wrapper generates a variable that is backed by UserDefaults.
/// This can be used with any Codable type, and saves the item to disk as Data.
/// At initialization, you supply the key at which the the variable will be
/// saved, and the instance of UserDefaults in which to save it.
///
/// Like any other variable, it can be made get-only using `private(set)`, to
/// allow for better encapsulation, if so desired.
///
/// Example usage:
/// ```
/// @DiskBacked(key: "myObject", userDefaults: .standard)
/// private(set) var myObject: MyObject?
/// ```
@propertyWrapper
struct DiskBacked<T: Codable> {{
private let key: String
private let userDefaults: UserDefaults
var wrappedValue: T? {
get {
userDefaults.codable(forKey: key)
}
set {
try? userDefaults.saveCodable(newValue, forKey: key)
}
}
init(key: String, userDefaults: UserDefaults) {
self.key = key
self.userDefaults = userDefaults
}
}
private extension UserDefaults {
func saveCodable<T: Codable>(_ object: T, forKey key: String) throws {
let encoded = try JSONEncoder().encode(object)
setValue(encoded, forKey: key)
}
func codable<T: Codable>(forKey key: String) -> T? {
guard let encoded = data(forKey: key) else {
return nil
}
return try? JSONDecoder().decode(T.self, from: encoded)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment