NSNotificationCenter将结构作为UserInfo的一部分传递

时间:2015-03-02 11:37:09

标签: swift struct nsnotification userinfo

由于NSNotificationCenter.defaultCenter()。postNotificationName userinfo仅接受数据符合AnyObject协议的字典,是否有人建议如何在NSNotification中发布结构?

我最初的想法是将结构包装在一个类中 - 但是那么首先使用结构的重点是什么。

我是否遗漏了某些内容,或者这只是将Swift与为Objective C构建的API混为一谈的结果?

以下是我所描述的内容的演示: -

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 个答案:

答案 0 :(得分:30)

问题是原始的Obj-C方法需要一个NSDictionary,它只将对象类型作为键和值,转换为Swift中的[AnyObject:AnyObject],除了NSDictionary喜欢将其键与isEqual进行比较:这是在NSObject协议中,密钥必须是NSObject(我不知道NSObjectProtocol是否足够,但Apple决定将它变为NSObject)。 因此,NSDictionary userInfo必须是Swift中的[NSObject:AnyObject],所以你不能在那里放置一个结构,我也不相信你可以在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的var来使它变得不可变。