Created
July 6, 2022 23:53
-
-
Save eliyap/18a5500d059f0df5c18757045cf8894a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
protocol Initializable: RawRepresentable { | |
init?(rawValue: RawValue) | |
} | |
enum Person: Int, Initializable { | |
case andrew | |
} | |
final class Preferences { | |
static let standard = Preferences(userDefaults: .standard) | |
fileprivate let userDefaults: UserDefaults | |
/// Sends through the changed key path whenever a change occurs. | |
var preferencesChangedSubject = PassthroughSubject<AnyKeyPath, Never>() | |
init(userDefaults: UserDefaults) { | |
self.userDefaults = userDefaults | |
} | |
@UserDefault("should_show_hello_world") | |
var shouldShowHelloWorld: Person = .andrew | |
} | |
@propertyWrapper | |
struct UserDefault<Value: Initializable> { | |
let key: String | |
let defaultValue: Value | |
var wrappedValue: Value { | |
get { fatalError("Wrapped value should not be used.") } | |
set { fatalError("Wrapped value should not be used.") } | |
} | |
init(wrappedValue: Value, _ key: String) { | |
self.defaultValue = wrappedValue | |
self.key = key | |
} | |
public static subscript( | |
_enclosingInstance instance: Preferences, | |
wrapped wrappedKeyPath: ReferenceWritableKeyPath<Preferences, Value>, | |
storage storageKeyPath: ReferenceWritableKeyPath<Preferences, Self> | |
) -> Value { | |
get { | |
let container = instance.userDefaults | |
let key = instance[keyPath: storageKeyPath].key | |
let defaultValue = instance[keyPath: storageKeyPath].defaultValue | |
let value = container.object(forKey: key) | |
if Value.self is (any Initializable), let value = value as? Value.RawValue { | |
return Value(rawValue: value) ?? defaultValue | |
} else { | |
return value as? Value ?? defaultValue | |
} | |
} | |
set { | |
let container = instance.userDefaults | |
let key = instance[keyPath: storageKeyPath].key | |
container.set(newValue, forKey: key) | |
instance.preferencesChangedSubject.send(wrappedKeyPath) | |
} | |
} | |
} |
Author
eliyap
commented
Jul 7, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment