KVO 不适用于 NSManagedObject 的自定义 属性
KVO not working for custom property of NSManagedObject
我有一个 NSManagedObject Folder
的子类,状态为 Availability
@objc enum Availability: Int16 {
case unknown
case available
case unavailable
}
只要可用性发生变化,文件夹就必须执行额外的操作(例如删除相关文件)。所以我有
internalAvailability
保存在核心数据中
- 使用上面的 属性
计算 属性 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 合规性明确添加到 属性 中,希望它开始起作用,但遗憾的是没有结果。
编辑:如果我在 internalAvailability
而不是 availability
上创建 DynamicProperty
,一切都会顺利..
添加为答案,因为它已成为一个学习练习。希望其他人也会受益。
该应用使用多 managedObjectContext(moc) 架构。 1 个用于进行更改的私有 moc 和 1 个使用 mergeChanges.
同步自身的主线程 moc
在上面的代码中,navigationItem
使用了与 main-moc 一起保存的文件夹实例。 DynamicProperty 正在侦听此 main-moc 的文件夹实例上的 KVO 更改。让我们称之为主文件夹。当我进行更改时,我会修改我们在 private-moc 上的文件夹实例。我们称它为私人文件夹。
在修改私有文件夹并在私有 moc 上调用 save
时,会广播名称为 NSManagedObjectContextDidSave
的通知。 main-moc 使用 mergeChanges 同步自身。
mergeChanges 更改主文件夹,但请注意它永远不会调用计算-属性-setter availability
。直接改变internalAvailability
.
因此,我们计算的 属性 没有发布 KVO 通知。
TL;DR 在 NSManagedObject 子类上执行 KVO 时,使用存储的 属性 而不是计算的。如果您有一个多 moc(托管对象上下文)场景并使用 mergeChanges 进行同步,则在同步时不会调用您计算的 属性 的 setter。
编辑(解决方案):添加模式的方法keyPathsForValuesAffecting<KeyName>
KVO relevant documentation
@objc class func keyPathsForValuesAffectingAvailability() -> Set<NSObject> {
return [#keyPath(Folder.internalAvailability) as NSObject]
}
在使用 Core Data 时,我们使用 NSManagedObjectContextObjectsDidChange
通知而不是 KVO。这带来了许多优势,包括合并变更事件和撤消支持。如果我们需要知道对象的哪些属性发生了变化,我们可以检查 changedValuesForCurrentEvent
,它甚至包括具有匹配 keyPathsForValuesAffecting...
的临时属性。这些优势可能超过 KVO 绑定框架(即反应式)的优势。
我有一个 NSManagedObject Folder
的子类,状态为 Availability
@objc enum Availability: Int16 {
case unknown
case available
case unavailable
}
只要可用性发生变化,文件夹就必须执行额外的操作(例如删除相关文件)。所以我有
internalAvailability
保存在核心数据中- 使用上面的 属性 计算 属性
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 合规性明确添加到 属性 中,希望它开始起作用,但遗憾的是没有结果。
编辑:如果我在 internalAvailability
而不是 availability
上创建 DynamicProperty
,一切都会顺利..
添加为答案,因为它已成为一个学习练习。希望其他人也会受益。
该应用使用多 managedObjectContext(moc) 架构。 1 个用于进行更改的私有 moc 和 1 个使用 mergeChanges.
同步自身的主线程 moc在上面的代码中,navigationItem
使用了与 main-moc 一起保存的文件夹实例。 DynamicProperty 正在侦听此 main-moc 的文件夹实例上的 KVO 更改。让我们称之为主文件夹。当我进行更改时,我会修改我们在 private-moc 上的文件夹实例。我们称它为私人文件夹。
在修改私有文件夹并在私有 moc 上调用 save
时,会广播名称为 NSManagedObjectContextDidSave
的通知。 main-moc 使用 mergeChanges 同步自身。
mergeChanges 更改主文件夹,但请注意它永远不会调用计算-属性-setter availability
。直接改变internalAvailability
.
因此,我们计算的 属性 没有发布 KVO 通知。
TL;DR 在 NSManagedObject 子类上执行 KVO 时,使用存储的 属性 而不是计算的。如果您有一个多 moc(托管对象上下文)场景并使用 mergeChanges 进行同步,则在同步时不会调用您计算的 属性 的 setter。
编辑(解决方案):添加模式的方法keyPathsForValuesAffecting<KeyName>
KVO relevant documentation
@objc class func keyPathsForValuesAffectingAvailability() -> Set<NSObject> {
return [#keyPath(Folder.internalAvailability) as NSObject]
}
在使用 Core Data 时,我们使用 NSManagedObjectContextObjectsDidChange
通知而不是 KVO。这带来了许多优势,包括合并变更事件和撤消支持。如果我们需要知道对象的哪些属性发生了变化,我们可以检查 changedValuesForCurrentEvent
,它甚至包括具有匹配 keyPathsForValuesAffecting...
的临时属性。这些优势可能超过 KVO 绑定框架(即反应式)的优势。