我有一个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合规性明确添加到该物业中,希望它能开始工作,但可惜没有结果。

    编辑:如果我在DynamicProperty而不是internalAvailability上创建availability,那么一切都会顺利进行。

    最佳答案

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

    该应用程序使用多个ManagedObjectContext(moc)架构。 1个 private moc进行更改,还有1个主线程moc使用mergeChanges进行自身同步。

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

    在修改专用文件夹并在private-moc上调用save时,将广播名称NSManagedObjectContextDidSave的通知。 main-moc使用mergeChanges进行自身同步。

    mergeChanges更改主文件夹,但请注意,它将永远不会调用计算属性设置者availability。它直接更改internalAvailability

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

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

    编辑(解决方案):模式keyPathsForValuesAffecting<KeyName> KVO relevant documentation添加方法

    @objc class func keyPathsForValuesAffectingAvailability() -> Set<NSObject> {
      return [#keyPath(Folder.internalAvailability) as NSObject]
    }
    

    关于ios - KVO无法用于NSManagedObject的自定义属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52643702/

    10-14 23:31
    查看更多