【问题标题】:NSNotificationCenter passing structs as part of the UserInfoNSNotificationCenter 将结构作为 UserInfo 的一部分传递
【发布时间】:2015-05-02 18:00:35
【问题描述】:

由于 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

【问题讨论】:

    标签: swift struct nsnotification userinfo


    【解决方案1】:

    问题是原始的 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
    

    这是一个可变包装器,您可以随意通过将 var 切换为 let 来使其不可变。

    【讨论】:

    • 我从来没有使用过泛型,所以我花了一些时间试图确定如何找回我的 Struct。我使用了通知对象,但是如果 let wrapperItem = notification.object as 的概念是一样的? Wrapper { let foo = wrapperItem.wrappedValue }
    • 当我在 AddObserver 上的 userinfo 字典中时如何获取值?
    • 让editedStruct = payload.userInfo?["approval"] as? Wrapper 并查看值 print((editedStruct?.wrappedValue.aValue)! as String) @DogCoffee
    • 除了使用包装器,也许返回一个带有扩展功能的包装对象也不错
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    相关资源
    最近更新 更多