I'm assembling a class which has several states, as defined by an enum, and a read-only property "state" which returns the instance's current state. I was hoping to use KVO techniques to observe changes in state but this doesn't seem possible:
dynamic var state:ItemState // Generates compile-time error: Property cannot be marked dynamic because its type cannot be represented in Objective-C
I guess I could represent each state as an Int or String, etc. but is there a simple alternative workaround that would preserve the type safety that the enum would otherwise provide?
Vince.
Perhaps this is only available in swift 2+, but you can make an enum property directly observable without having to refer to its rawValue. It does come with some limitations however.
NSObject
(directly or indirectly)@objc
Int
dynamic
.class SomeModel : NSObject { // (1) extend from NSObject
@objc // (2) mark enum with @objc
enum ItemState : Int, CustomStringConvertible { // (3) extend enum from Int
case Ready, Set, Go
// implementing CustomStringConvertible for example output
var description : String {
switch self {
case .Ready: return "Ready"
case .Set: return "Set"
case .Go: return "Go"
}
}
}
dynamic var state = ItemState.Ready // (4) declare property as dynamic
}
Elsewhere:
class EnumObserverExample : NSObject {
private let _model : SomeModel
init(model:SomeModel) {
_model = model
super.init()
_model.addObserver(self, forKeyPath:"state", options: NSKeyValueObservingOptions.Initial, context: nil)
}
deinit {
_model.removeObserver(self, forKeyPath:"state", context: nil)
}
override func observeValueForKeyPath(keyPath: String!, ofObject object: AnyObject!, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if "state" == keyPath {
print("Observed state change to \(_model.state)")
}
}
}
let model = SomeModel()
let observer = EnumObserverExample(model:model)
model.state = .Set
model.state = .Go
Outputs:
Observed state change to Ready (because .Initial was specified)
Observed state change to Set
Observed state change to Go