快速观察结构或类中的所有属性

问题描述

我有一个iOS应用,我想在其中使用Google Cloud Firestore来存储用户偏好设置,但是我想出一个优雅的解决方案来解决我的问题,该解决方案在更改以下任何一项后都可以调用我的saveSettingsToFirestore() Settings结构的属性

我当然不希望在应用程序中修改设置的每个实例之后手动调用我的saveSettingsToFirestore()函数。我想我可以在此Settings结构的所有15个以上的属性中放置一个单独的“ didSet”属性观察器,但这看起来很难看,我无法想象这是最佳实践。

我已经考虑过KVO,但是找不到适合我的案例的好例子,并且在设置它时遇到了困难。

同样,如果您有更好的解决方案来管理与用户帐户相关联的一组变量,请告诉我。我特别不使用NSUserDefaults,因为我想将数据与用户ID而不是用户的iCloud帐户关联。

这是我要观察的结构:

struct Settings: Codable {
  
  static var shared = Settings()
  
  var hideTimesAfter = "10:00 PM"
  var hideTimesBefore = "5:00 AM"
  
  var increment = 15
  var nextColorIndex = 1
  
  var adsEnabled = true
  var alertsEnabled = true
  var bugShakeEnabled = true
  var didSeeIOSUpdateRequest = false
  var firstTime = true
  var isIdleTimerdisabled = false
  var notificationsEnabled = true
  var premiumEnabled = false
  var soundsEnabled = true
  var twentyFourHourModeEnabled = false
  var vibrationsEnabled = true

  private init() { }
}

这是我尝试与观察者将struct重组为NSObject class的尝试,但我仍在尝试弄清楚行进方向,并希望从中获得任何见识。

class Settings: NSObject,Codable {
  
  static let shared = Settings()
  
  @objc dynamic var hideTimesAfter = "10:00 PM"
  @objc dynamic var hideTimesBefore = "5:00 AM"
  
  @objc dynamic var increment = 15
  @objc dynamic var nextColorIndex = 1
  
  @objc dynamic var adsEnabled = true
  @objc dynamic var alertsEnabled = true
  @objc dynamic var bugShakeEnabled = true
  @objc dynamic var didSeeIOSUpdateRequest = false
  @objc dynamic var firstTime = true
  @objc dynamic var isIdleTimerdisabled = false
  @objc dynamic var notificationsEnabled = true
  @objc dynamic var premiumEnabled = false
  @objc dynamic var soundsEnabled = true
  @objc dynamic var twentyFourHourModeEnabled = false
  @objc dynamic var vibrationsEnabled = true

  func updateDate() {
      print("yo firestore,get this shit")
  }
  
  let observed = Settings.shared
  let observer = MyObserver(object: observed)

}

class MyObserver: NSObject {
    @objc var objectToObserve: Settings
    var observation: NSkeyvalueObservation?
    
    init(object: Settings) {
        objectToObserve = object
        super.init()
        
        observation = observe(
            \.objectToObserve.adsEnabled,options: [.old,.new]
        ) { object,change in
            print("myDate changed from: \(change.oldValue!),updated to: \(change.newValue!)")
        }
    }
}

解决方法

如果所有(或几乎所有)这些设置都在单个视图控制器中进行了更改,那么我不会考虑使用KVO模型或放弃对较新框架的OS支持,因为您的问题确实比应有的问题简单得多更简单的解决方案。

您不必在乎这些设置的各个值更改,因为那意味着您在乎每次用户更改数据库时都更新数据库。即使使用Firestore的定价模型,效率也不高。您应该关心的是,当用户完成对视图控制器的操作后,任何值都没有更改-如果更改了该值,则您想在用户下方更新数据库(他们不需要等待或点击保存按钮,因为Firestore具有脱机功能。

因此,当用户打开此视图控制器时,只需将这些设置的当前值记录在视图控制器本身中(也许在viewDidLoad中),当用户离开视图控制器时,请检查是否存在任何值已更改(也许在viewWillDisappear中);如果是,则更新数据库。