NSNotificationCenter передает структуры как часть UserInfo
Из-за NSNotificationCenter.defaultCenter(). PostNotificationName userinfo принимает только словари с данными, соответствующими протоколу AnyObject, есть ли у кого-нибудь какие-либо предложения о том, как публиковать структуры как часть NSNotification?
Моя первоначальная мысль заключалась в том, чтобы обернуть структуру в классе, но тогда какой смысл использовать структуру в первую очередь.
Я что-то упустил или это просто результат объединения Swift с API, созданным для Objective C?
Вот демонстрация того, что я описываю:
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
1 ответ
Проблема заключается в том, что исходный метод Obj-C требует NSDictionary, который принимает только типы объектов в качестве ключей и значений, что преобразуется в [AnyObject: AnyObject] в Swift, за исключением того, что NSDictionary любит сравнивать свои ключи с isEqual: который находится в NSObject. протокол, поэтому ключ должен быть NSObject (я не знаю, было ли достаточно NSObjectProtocol, но Apple решила сделать его NSObject). Следовательно, NSDictionary userInfo должно быть [NSObject: AnyObject] в Swift, и поэтому вы не можете поместить туда структуру, и я не верю, что вы могли бы и в Objective-C.
К сожалению, обертка будет необходимо. Мы могли бы поиграть с NSValue и создать что-то уродливое и неэффективное, но в любом случае лучшее решение - созданная вами оболочка.
Однако вы создали подкласс NSObject, который не был необходим, поэтому вы можете выбросить этот код:)
class Wrapper {
var aStructToWrap: aStruct
init(theStruct: aStruct) {
aStructToWrap = theStruct
}
}
struct aStruct {
var aValue: String
}
За исключением того, что мы можем сделать еще лучше! Мы можем сделать универсальную оболочку для любой структуры или значения (или даже объекта), которые вам нравятся.
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
Это изменяемая оболочка, не стесняйтесь делать ее неизменной, переключая переменную на let.