StorageValue.swift 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // LoopFollow
  2. // StorageValue.swift
  3. import Combine
  4. import Foundation
  5. class StorageValue<T: Codable & Equatable>: ObservableObject {
  6. let key: String
  7. @Published var value: T {
  8. didSet {
  9. guard value != oldValue else { return }
  10. if let encodedData = try? JSONEncoder().encode(value) {
  11. StorageValue.defaults.set(encodedData, forKey: key)
  12. }
  13. }
  14. }
  15. var exists: Bool {
  16. return StorageValue.defaults.object(forKey: key) != nil
  17. }
  18. private static var defaults: UserDefaults {
  19. return UserDefaults.standard
  20. }
  21. init(key: String, defaultValue: T) {
  22. self.key = key
  23. if let data = StorageValue.defaults.data(forKey: key),
  24. let decodedValue = try? JSONDecoder().decode(T.self, from: data)
  25. {
  26. value = decodedValue
  27. } else {
  28. value = defaultValue
  29. }
  30. }
  31. func remove() {
  32. StorageValue.defaults.removeObject(forKey: key)
  33. }
  34. /// Re-reads the value from UserDefaults, updating the @Published cache.
  35. /// Call this when the app foregrounds after a Before-First-Unlock background launch,
  36. /// where StorageValue was initialized while UserDefaults was locked (returning defaults).
  37. func reload() {
  38. if let data = StorageValue.defaults.data(forKey: key),
  39. let decodedValue = try? JSONDecoder().decode(T.self, from: data),
  40. decodedValue != value
  41. {
  42. value = decodedValue
  43. }
  44. }
  45. }