Swift(KVO)中有没有一种方法可以创建可观察的枚举

nlejzf6q  于 12个月前  发布在  Swift
关注(0)|答案(4)|浏览(108)

我尝试在MVVM中使用RxSwift进行绑定。我有一个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"

我在这里发现,要使类不是从NSObject继承,我应该使它成为dynamic,但我不能使Enum动态。有没有办法让Enum变得可观察?

kmynzznz

kmynzznz1#

您不需要使用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.
}
a6b3iqyw

a6b3iqyw2#

因为你的枚举类型是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)")
        }
    }
}
lymnna71

lymnna713#

我可以建议只做一个代理变量,并在上面使用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/

k4emjkb1

k4emjkb14#

如果应用程序支持的最低iOS版本为13.0或更高版本,则可以使用合并并将属性设置为@Published

class Test : NSObject {
    @Published var color: Color = .Red

    dynamic var test: String? {
        didSet {
            print("didSet \(test)")
        }
    }
}

这样观察它:

let test = Test()
test.$color.sink(receiveValue: { color in
    print(color)
})

相关问题