swift: how to notify native data change?

Hello,


Trying to notify my swift classes when a enum (with associated values) property changes, and found that all my objective-c tricks failed for swift...


First tried KVO: not working since the property is not an objective-c compatible type

Then tried NSNotification in didSet, still not able to do it, since the userInfo only take [NSObject: AnyObject].


The raionale, as I understood, is that these types have no coresponding representation in objective-c, thus the lowest denominator. So how should one propagate changes in Swift land? Will there be swift-only API that can extend these feature to native swift types? Maybe there are some elegant solutions out there already? Does anybody encounter similar situations and how do you resolve it?


[update]

After moving beyond the userInfo, bumped into more Notification system's AnyObject constraint in both addObserver and postNotification API. Which means not only a struct can't send notification natively, it can't observe any notification either without "pretending" to be a class... Basically NSNotificationCenter doesn't know how to deal with swift value types. If swift value types can carry behavior and indeed have valid "identity" in the system, I am not sure why these objetive-c systems (such as Notification, KVO) shouldn't evovle to handle them, at least as an opague instance? ...

As long as the notification sender and the listeners are classes, you could make NSNotificationCenter work.

Either have the notification handler code ask the sender for the updated value directly, or send the value in a simple wrapper class in the userInfo.

If you want to send the enum, you can do it with a wrapper:


class Wrapper<E> {
    let value : E
    init(value: E) {
        self.value = value
    }
}

thanks for the suggestions, yes the class wrappers can indeed pass data along in userInfo. But for KVO-like feature, we will need to associate these info with an "instance", which is declared, again, as AnyObject in Notificaiton post/observe api. How does one post a structure's property change in a way that the other class/structure can observe for the specific instance's change? Of course the structure can carry a dummy (AnyObject) property as the "target" for post/observe, but it seems twisted, heavy and hacky... can we do better?

Honestly, if you want a notification-style model to work properly, the objects observing probably should be classes.


The observers need to have a stable identity, so that there is a valid target for the callback.

The observers need to allow the "notification center" object to keep a reference to them rather than a copy of them, so that the observer is the original object.

The observers need a way to deregister themselves when they go out of scope, so that the "notification center" doesn't try to access a deallocated observer.


There are things that structs are great at... the qualities listed above are not any of those things.


Using classes for types that need to listen for notifications, and using the existing NSNotification system is just simpler in most cases.


You can use a unique-per-instance generated String as the sender for the notifications, if the property you are observing belongs to something that ought to be a struct, in order to match notifications originating from a particular struct instance.


But trying to create a system where the observing objects are value types is a recipe for pain and random crashing.

Yes, I agree. Since structs and enums are immutable, it doesn't make sense to be notified when they are mutated. We should think about structs and enums the same way we think about NSString, NSDictionary, NSArray, and so on. I thought the original question was about mutating a property in a class that happened to be a value type, and therefore not representable in Objective-C.

Indeed, that was the original question, after moving beyond the userInfo, I bumped into more AnyObject constraint in the Notification system. Updated the post to make it clear

After moving beyond the userInfo, bumped into more Notification system's AnyObject constraint in both addObserver and postNotification API. Which means not only a struct can't send notification natively, it can't observe any notification either without "pretending" to be a class... Basically NSNotificationCenter doesn't know how to deal with swift value types. If swift value types can carry behavior and indeed have valid "identity" in the system, I am not sure why these objetive-c systems (such as Notification, KVO) shouldn't evovle to handle them, at least as an opague instance? ...


However I am not sure that I agree with that only class change can be observed... a struct does have persistent "identity", just like a class, it has behavior and can indeed mutate if desired. And besides, a struct should definitely be able to observe notification, which it can't either today, at least not without any hacking...

swift: how to notify native data change?
 
 
Q