2016-03-16 7 views
4

Я пытаюсь использовать RxSwift для привязки в MVVM. У меня есть Enum:Есть ли способ сделать наблюдаемое перечисление в Swift (KVO)

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) 

Но программа chashes с *** 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 наблюдаемым?

ответ

0

Я могу предложить только сделать прокси-переменную и использовать 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/

1

Потому что ваше перечисление имеет тип Int, вы можете сделать это Objective-C совместимый пометив его с @objc. Это сделает компилятор в порядке с отметкой свойства как dynamic.

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

class Test : NSObject { 
    dynamic var color: Color = .Red 
    dynamic var test: String? { 
     didSet { 
      print("didSet \(test)") 
     } 
    } 
} 
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. 
}