【问题标题】:Is there a way to make observable enum in Swift (KVO)有没有办法在 Swift (KVO) 中制作可观察的枚举
【发布时间】:2016-03-16 09:31:07
【问题描述】:

我正在尝试使用 RxSwift 在 MVVM 中进行绑定。 我有一个Enum

enum Color : Int {
    case Red = 0, Green
}

测试类

class Test : NSObject {
    var color: Color = .Red
    dynamic var test: String? {
        didSet {
            print("didSet \(test)")
        }
    }
}

并想观察如下变化:

test.rx_observe(Color.self, "color").subscribeNext { (color) -> Void in
     print("Observer \(color)")
}.addDisposableTo(bag)

但该程序与 *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<RDProject.Test 0x7ff373513020> addObserver:<RxCocoa.KVOObserver 0x7ff37351a420> forKeyPath:@"color" options:5 context:0x0] was sent to an object that is not KVC-compliant for the "color" property.'

简单的String 代码有效:

test.rx_observe(String.self, "test").subscribeNext { string in
     print("Observer \(string)")
}.addDisposableTo(bag)

test.test = "1"
test.test = "2"

我发现here 让类继承自NSObject 我应该将其设为dynamic,但我不能将Enum 设为动态。 有没有办法让Enum 可观察?

【问题讨论】:

    标签: swift key-value-observing rx-swift


    【解决方案1】:

    您不需要为此任务使用 KVO。 只需使用这样的 BehaviorSubject:

    创建一个像这样的私有字段:

    let colorSubject = BehaviorSubject<Color?>(value: nil)
    

    然后你有一个像这样的属性,它通知 BehaviorSubject 值确实发生了变化。

    var color : Color? {
        didSet {
            colorSubject.onNext(color)
        }
    }
    

    要订阅任何更改,请使用与此等效的语句:

    let disposable = colorSubject.subscribeNext { (color: Color?) -> Void in
        // Do something with it.
    }
    

    【讨论】:

      【解决方案2】:

      因为你的枚举类型是Int,你可以通过标记@objc使它与objective-c兼容。这样做将使编译器可以将属性标记为dynamic。要使该属性符合 KVO,还需要使用 @objc 进行注释。

      @objc enum Color : Int {
          case Red = 0, Green
      }
      
      class Test : NSObject {
          @objc dynamic var color: Color = .Red
          dynamic var test: String? {
              didSet {
                  print("didSet \(test)")
              }
          }
      }
      

      【讨论】:

      • 嗨。我正在使用 Swift 5 并尝试了这个解决方案。不幸的是,它与Fatal error: Could not extract a String from KeyPath Swift.ReferenceWritableKeyPath ... 崩溃了,您能确认这仍然有效吗?
      • 它确实崩溃了,但是用 @objc 注释该字段可以修复崩溃并使此功能再次起作用。我更新了我的答案以反映这一点。希望对您有所帮助:)
      • 感谢您的回复! --- 这确实解决了问题。首先,它是Error 类型的枚举,将其更改为Int 是第一步。 --- 然后,用@objc 注释枚举和属性是完成这项工作的最后一步。 --- 然后我还有一个问题是属性是MyEnumType?,所以是可选的。这不能在 Objective-C 中表示。我不认为这可以解决。但是你回答了我的问题,这很有效:-)
      【解决方案3】:

      我可以建议只创建一个代理变量并在其上使用 KVO。

      class Model: NSObject {
      
          enum Color: Int {
              case Red = 0, Green
          }
      
          dynamic var colorRaw: Int?
          var color: Color = .Red {
              didSet {
                  colorRaw = color.rawValue
              }
          }
      
      }
      

      更多细节在这里 - https://christiantietze.de/posts/2015/05/observing-enum-swift-kvo/

      【讨论】:

        猜你喜欢
        • 2015-02-02
        • 2011-07-13
        • 1970-01-01
        • 2014-08-02
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        相关资源
        最近更新 更多