【问题标题】:Type Error in closure (translated code from obj c to swift)闭包中的类型错误(将代码从 obj c 转换为 swift)
【发布时间】:2014-07-31 23:01:44
【问题描述】:

我正在尝试在我的 swift 应用程序中使用一个用目标 c 编写的库。 我试图将自述文件中的 sn-p 转换为 swift 代码 - 但我收到一个我不理解的类型错误。

自述文件中的 Obj.C 代码:

[self.client logonWithUsername:self.username.text password:self.password.text responseCallback:^(NSDictionary *response, NSError *error) {
    if (error) {
        [self handleFailedAuth:error];
        return;
    }
    [self handleSuccessfulAuth];
}];

我对 swift 的翻译:

    var username = NSUserDefaults.standardUserDefaults().stringForKey("username")
    var password = NSUserDefaults.standardUserDefaults().stringForKey("password")

    client.logonWithUsername(username, password: password, responseCallback: {
        (response: NSDictionary, error: NSError) in
            if(error){
                handleFailedAuth(error)
                return;
            }
            handleSuccessfulAuth()
        }
    )

我得到 [NSObject: AnyObject]!不是定义闭包参数的那一行的 NSDictionary 的子类型。这怎么可能?我使用与示例中相同的类型。

【问题讨论】:

  • 尝试在 NSDictionary 之后添加一个感叹号。 NSError 以及
  • 是的,我想说这就是问题所在。您没有使用 quite 相同的类型,因为 Objective C 中的 NSDictionary* 可以为零。 Swift 中的 NSDictionary 不能为零:您需要某种 Optional。这些对象指针从 Objective C 标头中桥接为隐式展开,因此需要使用 NSDictionary!
  • 只需删除类型,让编译器为您计算出来
  • 是的,公平点:在这种情况下总是可以推断类型。虽然显然 it might be a little buggy 在测试版中。
  • 好吧,我不知道为什么,但是编译器并没有真正帮助我找到正确的时间——可能是因为测试版...使用 NSDictionary!并没有真正的帮助 - 现在错误是 [NSObject: AnyObject] 与 NSDictionary 不同

标签: objective-c swift xcode6


【解决方案1】:

你的 Swift 应该是这样的:

var username = NSUserDefaults.standardUserDefaults().stringForKey("username")
    var password = NSUserDefaults.standardUserDefaults().stringForKey("password")

    client.logonWithUsername(username, password: password, responseCallback: {
        (response: NSDictionary?, error: NSError?) in
            if(error){
                handleFailedAuth(error!)
                return;
            }
            handleSuccessfulAuth()
        }
    )

这是因为 Swift 的可选项在某些方面取代了您过去在 Objective-c 中传递 nil 的方式。因此,因为 NSDictionary 可能是 nil 而 NSError 可能是 nil,所以你在它们之后放置一个 ? 标记,然后当你需要访问它的值时,有条件地在块内打开一个 ! 标记

【讨论】:

    【解决方案2】:

    您在 Swift 中明确指定了块/闭包参数类型,而 Swift 编译器没有足够的关于 NSDictionary 的信息。这是因为 Swift Dictionary 的类型比 Objective-C NSDictionary 更强。

    错误消息说(诚然,相当神秘)Swift 所期望的确切类型是Dictionary<NSObject, AnyObject>!

    有几种方法可以解决这个问题。一种是在 Swift 闭包定义中更明确地说明您的 NSDictionary 参数:-

      client.logonWithUsername(username, password: password, responseCallback: {
        (response: Dictionary<NSObject, AnyObject>!, error: NSError) in
          // ... handler body
          }
      )
    

    一种更简单的方法是根本不告诉 Swift 类型,让编译器推断它需要什么:-

      client.logonWithUsername(username, password: password, responseCallback: {
        response, error in
          // ... handler body
          }
      )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多