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.

Другие вопросы по тегам