swift 4 nsnotificationcenter
NSNotificationCenter pasa las estructuras como parte de UserInfo (1)
Debido a NSNotificationCenter.defaultCenter (). PostNotificationName userinfo que solo acepta diccionarios con datos que cumplen con el protocolo AnyObject, ¿alguien tiene alguna sugerencia sobre cómo publicar estructuras como parte de una NSNotification?
Mi idea inicial es envolver la estructura en una clase, pero entonces, ¿cuál sería el punto de usar una estructura en primer lugar?
¿Me estoy perdiendo algo o es solo el resultado de la combinación de Swift con la API creada para Objective C?
Aquí hay una demostración de lo que estoy describiendo:
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
El problema es que el método Obj-C original requiere un NSDictionary, que solo toma tipos de objetos como claves y valores, lo que se traduce en [AnyObject: AnyObject] en Swift, excepto que a NSDictionary le gusta comparar sus claves con isEqual: que está en el NSObject protocolo, por lo que la clave debe ser un NSObject (no sé si NSObjectProtocol fue suficiente, pero Apple ha decidido convertirlo en un NSObject). Por lo tanto, la información de usuario de NSDictionary debe ser [NSObject: AnyObject] en Swift, por lo que no puede poner una estructura allí, y tampoco creo que pueda en Objective-C.
Lamentablemente será necesaria una envoltura. Podríamos jugar con NSValue y producir algo feo e ineficiente, pero en cualquier caso, la mejor solución es la envoltura que ha creado.
Sin embargo, hiciste una subclase de NSObject, que no era necesaria, así que puedes tirar ese código :)
class Wrapper {
var aStructToWrap: aStruct
init(theStruct: aStruct) {
aStructToWrap = theStruct
}
}
struct aStruct {
var aValue: String
}
Excepto que podemos hacerlo aún mejor! Podemos hacer una envoltura genérica para cualquier estructura o valor (o incluso objeto) que desee.
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
Esa es una envoltura mutable, siéntase libre de hacerla inmutable cambiando la var por una let.