Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make observable enum in Swift (KVO)

I'm trying to use RxSwift for binding in MVVM. I have a Enum:

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

and class for test

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

And want to observe changes like:

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

But the program chashes with *** 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.'

Code for simple String works:

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

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

I found here that to make class inherited not from NSObject I should make it dynamic, but I can't make Enum dynamic. Is there a way to make Enum observable?

like image 736
katleta3000 Avatar asked Mar 16 '16 09:03

katleta3000


2 Answers

You don't need to use KVO for this task. Just use a BehaviorSubject like this:

Create a private Field like this one:

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

Then you have a property like this which informs the BehaviorSubject that the value did change.

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

To subscribe to any change use an equivalent statement to this one:

let disposable = colorSubject.subscribeNext { (color: Color?) -> Void in
    // Do something with it.
}
like image 161
Sebastian Krogull Avatar answered Nov 03 '22 00:11

Sebastian Krogull


Because your enum is of type Int, you can make it objective-c compatible by marking it with @objc. Doing this will make compiler ok with marking the property as dynamic. For the property to be KVO compliant, it'll also need to be anotated with @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)")
        }
    }
}
like image 27
tomahh Avatar answered Nov 03 '22 01:11

tomahh