2

我有一个 NSManagedObject 的子类Folder,其状态为Availability

@objc enum Availability: Int16 {
  case unknown
  case available
  case unavailable
}

每当可用性发生变化时,文件夹都必须做额外的事情(例如删除相关文件)。所以我有

  1. internalAvailability保存在核心数据中
  2. availability使用上述属性计算的属性

`

extension Folder {
  @NSManaged private var internalAvailability: Availability
}

extension Folder {
  private func deleteFiles(...) {
  ...
  }

  @objc dynamic public var availability: Availability {
    get {
      return internalAvailability
    }
    set {
      willChangeValue(forKey: "availability")
      deleteFiles()
      internalAvailability = newValue
      didChangeValue(forKey: "availability")
    }
  }
}

使用 Reactive,我想根据可用性更改导航项的标题,但信号永远不会被调用一次!

```

let property = DynamicProperty<NSNumber>(object: folder, keyPath: "availability")
internalVariable = property // To have a reference of property

navigationItem.reactive.title <~ property.map { (stateNumber) -> String in
  guard let a = Availability(rawValue: stateNumber.int16Value) else {
      assertionFailure()
      return ""
  }
  let prefix = a == .available ? "" : "(Nope) "
  return "\(prefix)\(folder.name)"
}

我已明确将 KVO 合规性添加到该属性中,希望这可以开始工作,但遗憾的是没有结果。

编辑:如果我创建DynamicPropertyoninternalAvailability而不是availability,一切顺利..

4

2 回答 2

2

添加作为答案,因为它成为一个学习练习。希望其他人也能从中受益。

该应用程序使用多个 managedObjectContext(moc) 架构。1 个用于进行更改的私有 moc 和 1 个使用mergeChanges同步自身的主线程 moc 。

在上面的代码中,navigationItem使用的是与 main-moc 一起保存的文件夹实例。DynamicProperty 正在侦听此 main-moc 文件夹实例上的 KVO 更改。我们称之为主文件夹。当我进行更改时,我会修改我们在 private-moc 上的文件夹实例。我们称它为私人文件夹。

在修改私有文件夹和调用私有moc 时,会广播save名称通知。NSManagedObjectContextDidSavemain-moc 使用 mergeChanges 进行自身同步。

mergeChanges 更改主文件夹,但请注意它永远不会调用 computed-property-setter availability。它直接改变internalAvailability

因此,我们的计算属性不会发布任何 KVO 通知。

TL;DR在 NSManagedObject 子类上执行 KVO 时,使用存储属性而不是计算属性。如果您有一个多 moc(托管对象上下文)场景并使用mergeChanges进行同步,则同步时不会调用计算属性的设置器。

编辑(解决方案):添加模式keyPathsForValuesAffecting<KeyName> KVO相关文档的方法

@objc class func keyPathsForValuesAffectingAvailability() -> Set<NSObject> {
  return [#keyPath(Folder.internalAvailability) as NSObject]
}
于 2018-10-05T06:44:27.313 回答
1

当使用 Core Data 时,我们使用NSManagedObjectContextObjectsDidChange通知而不是 KVO。这带来了许多优势,包括更改事件的合并和撤消支持。如果我们需要知道对象上的哪些属性发生了变化,我们可以检查changedValuesForCurrentEvent哪些属性甚至包括具有匹配的瞬态属性keyPathsForValuesAffecting...。这些优势可能超过了 KVO 绑定框架(即反应式)的优势。

于 2020-03-31T09:42:22.553 回答