2015-03-02 8 views
16

Из-за NSNotificationCenter.defaultCenter(). PostNotificationName userinfo принимает только словари с данными, соответствующими протоколу AnyObject, есть ли у кого-нибудь какие-либо предложения о том, как публиковать структуры как часть NSNotification?NSNotificationCenter передает структуры как часть UserInfo

Вначале я подумал, что это нужно, чтобы обернуть структуру в классе, но тогда в чем смысл использования структуры в первую очередь.

Я что-то упустил или это просто результат объединения 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 

ответ

30

Вопрос заключается в том, что оригинальный метод Obj-C требует NSDictionary, который только принимает типы в качестве ключей и значений объекта, который переводит на [ AnyObject: AnyObject] в Swift, за исключением того, что NSDictionary любит сравнивать свои ключи с isEqual: который находится в протоколе NSObject, поэтому ключ должен быть NSObject (я не знаю, было ли NSObjectProtocol достаточным, но Apple решила сделать его NSObject). Следовательно, пользовательская информация NSDictionary должна быть [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 

Это изменчивая оболочка, не стесняйтесь сделать ее неизменной, переключив var на let.

+0

Я никогда не использовал дженерики, поэтому мне потребовалось некоторое время, пытаясь определить, как вернуть мою структуру. Я использовал объект уведомления, но концепция такая же, если пусть wrapperItem = notification.object как? Wrapper { let foo = wrapperItem.wrappedValue } – DogCoffee

+0

Как я могу получить значение, когда я нахожусь в словаре userinfo на AddObserver? – eddwinpaz

+0

let editStruct = payload.userInfo? ["Утверждение"] как? Wrapper и увидеть значение print ((editStruct? .wrappedValue.aValue)! As String) @DogCoffee – eddwinpaz