Due to NSNotificationCenter.defaultCenter().postNotificationName userinfo only accepting dictionaries with data complying with AnyObject protocol, does anyone have any suggestions how to post structs as part of an NSNotification?
My initial thought it is to wrap the struct in a class - but then what would be the point in using a struct in the first place.
Am I missing something or is this just a result of conflating Swift with API's built for Objective C?
Here's a demonstration of what I'm describing: -
class wrapper: NSObject {
var aStructToWrap: aStruct
init(theStruct: aStruct) {
aStructToWrap = theStruct
super.init()
}
}
struct aStruct {
var aValue: String
}
let aRealStruct = aStruct(aValue: "egg")
NSNotificationCenter.defaultCenter().postNotificationName("aKey", object: nil, userInfo: ["anotherKey": aRealStruct]) // ERR: Extra argument 'userinfo' in call
let wrappedStruct = wrapper(theStruct: aRealStruct)
NSNotificationCenter.defaultCenter().postNotificationName("aKey", object: nil, userInfo: ["anotherKey": wrappedStruct]) // no error
The issue is that the original Obj-C method requires an NSDictionary, which only takes object types as keys and values, which translates to [AnyObject: AnyObject] in Swift, except NSDictionary likes to compare its keys with isEqual: which is in the NSObject protocol, so the key must be an NSObject (I don't know if NSObjectProtocol was sufficient but Apple has decided to make it an NSObject). Therefore, the NSDictionary userInfo must be [NSObject: AnyObject] in Swift, and so you can't put a struct in there, and I don't believe you could in Objective-C either.
Sadly a wrapper will be necessary. We could play with NSValue and produce something ugly and inefficient, but in any case the best solution is the wrapper you have created.
However, you made a subclass of NSObject, that wasn't needed, so you can throw that code away :)
class Wrapper {
var aStructToWrap: aStruct
init(theStruct: aStruct) {
aStructToWrap = theStruct
}
}
struct aStruct {
var aValue: String
}
Except we can do even better! We can make a generic wrapper for any struct or value (or even object) you like.
class Wrapper<T> {
var wrappedValue: T
init(theValue: T) {
wrappedValue = theValue
}
}
struct aStruct {
var aValue: String
}
let aRealStruct = aStruct(aValue: "egg")
let wrappedStruct = Wrapper(theValue: aRealStruct)
NSNotificationCenter.defaultCenter().postNotificationName("aKey", object: nil, userInfo: ["anotherKey": wrappedStruct]) // no error
That's a mutable wrapper, feel free to make it immutable by switching the var for a let.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With