PersistedProperty.swift 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import Foundation
  2. /// Attention! Do not use this wrapper for mutating structure with `didSet` handler into property owner!
  3. /// `didSet` will never called if structure mutate into itself (by "mutating functions").
  4. @propertyWrapper struct Persisted<Value: Codable & Equatable> {
  5. var wrappedValue: Value {
  6. get { getValue() ?? initialValue }
  7. set { setValue(newValue) }
  8. }
  9. private func getValue() -> Value? {
  10. lock?.lock()
  11. defer { lock?.unlock() }
  12. return storage.getValue(Value.self, forKey: key)
  13. }
  14. private mutating func setValue(_ value: Value) {
  15. lock?.lock()
  16. defer { lock?.unlock() }
  17. storage.setValue(value, forKey: key)
  18. }
  19. private let key: String
  20. private let storage: KeyValueStorage
  21. private let lock: NSRecursiveLock?
  22. private let initialValue: Value
  23. var isInitialValue: Bool {
  24. if let value = getValue() {
  25. return value == initialValue
  26. }
  27. return true
  28. }
  29. init(
  30. wrappedValue: Value,
  31. key: String,
  32. storage: KeyValueStorage = UserDefaults.standard,
  33. lock: NSRecursiveLock? = nil
  34. ) {
  35. self.storage = storage
  36. self.key = key
  37. self.lock = lock
  38. initialValue = wrappedValue
  39. lock?.lock()
  40. defer { lock?.unlock() }
  41. if storage.getValue(Value.self, forKey: key) == nil {
  42. setValue(wrappedValue)
  43. }
  44. }
  45. }