【问题标题】:Cannot assign value of type NSDictionary to a value of type NSDictionary无法将 NSDictionary 类型的值分配给 NSDictionary 类型的值
【发布时间】:2015-07-17 20:20:27
【问题描述】:

Swift 2.0(Xcode 7 Beta 3),据我所知,语法看起来很棒。我之前获得了一个 JSON 字符串,然后当我尝试解析它时,我在“as”关键字的“try NSJSONSerialization”行中收到上述错误。我做错什么了?感谢您的回答。

        var weatherData: NSDictionary
        do {
            weatherData = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
        } catch {
            // Display an error to user
            let errorAlert = UIAlertController(title: "Error", message: "Unable to get weather data", preferredStyle: UIAlertControllerStyle.Alert)
            self.presentViewController(errorAlert, animated: true, completion: nil)
            return
        }

【问题讨论】:

  • weatherData 必须是 NSDictionary,而不仅仅是 Swift 风格的字典吗?

标签: swift nsdictionary nsjsonserialization swift2


【解决方案1】:

@EricD 在他的回答中写的是错误的。引用:

在 Swift 1.2 中使用 !很危险,最好使用 Optional 绑定(如果让 ...),但在 Swift 2 中,当您使用 do 处理错误时 抓住,你实际上可以使用! (但不要忘记使用 像你一样的通用捕获,除了可能的其他特定的 错误处理)。

do catch 仅处理且仅(重新)抛出的错误。没有其他的。如果您强制打开可选的 nil,您将收到 EXC_BAD_INSTRUCTIONfatal error: unexpectedly found nil while unwrapping an Optional value。即使您的代码包含在do catch 中,您也会得到它。像throwscatch 这样的关键字可以让人联想到它是关于异常的,但它不是——只是错误。同样适用于as!

改写成这样:

enum MyError: ErrorType {
  case ParsingFailed
}

// some jsonData you did receive
var jsonData: NSData?

do {
  guard let data = jsonData,
    weatherData = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? NSDictionary else {
      throw MyError.ParsingFailed
  }

  // here you can work with your weatherData dictionary in a safe way
  // it's NSDictionary and not an optional
}
catch {
  // Display an error to user
}

它的作用:

  • jsonData 包含(或不包含)您在回复中收到的NSData
  • guard let data = jsonData 尝试从 optional 中获取值,如果成功,解包后的值将存储在 data 中,否则将抛出 MyError.ParsingFailed
  • weatherData = ... 仅在前一个 guard 语句成功时执行,
    • 它尝试从数据中创建 JSON 对象,如果失败,则抛出错误,
    • 如果成功,它会尝试将其转换为 NSDictionary (as?),如果也成功,则 weatherData 包含您的 NSDictionary,否则将抛出 MyError.ParsingFailed

这是安全的,它不会崩溃,所有错误都在一个地方处理。

所以,不要使用@EricD 写的内容。即使在 Swift 2 中,使用 as!! 仍然很危险

NSData(contentsOfURL:options:) 也不是个好主意。这是同步调用,所以,它会阻塞你的主线程(应用看起来像被冻结),直到请求失败或成功。

【讨论】:

  • 我不知道我是怎么错过的,我之前肯定尝试过,但是......叹息。我已经编辑了这部分答案。非常感谢您的更新。
  • 好的,我觉得这是一个更完整、更好的答案。但是我如何才能精通理解 Swift 中的选项和错误处理呢?苹果的书只提供了这么多的阅读量,而没有提供这么多的理解深度。我一直在用一些昏暗的灯泡搜索这些主题。
  • David Owens - 从 6 月 9 日的一篇博文开始,其中有几篇是关于错误处理的,直到今天。 Airspeed Velocity 博客。 Swift Blog by Apple。 Twitter,...主要是-阅读,尝试,修复,阅读,尝试,修复,...
  • 好的,这个守卫声明很酷。但是,我在 Xcode 的 Swift 2 文档和 iBooks 的 Swift 2 编程指南中都找不到它。您在哪里找到该语法的文档?
  • Apple 的 Swift 编程语言 (Swift 2)。章节控制流 - 提前退出。
【解决方案2】:

您可以使用! 强制转换为NSDictionary(但最好使用@robertvojta 的答案中的“守卫”)。

另外,您可以使用[] 代替MutableContainers

weatherData = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! NSDictionary

编辑:根据@robertvojta 的回答和解释,我已经编辑了我关于 Swift 2 的错误断言,并在“do ... catch”中强制转换。另外,请注意,在屏幕截图中,NSData 仅用于在 Playground 中进行快速测试。

【讨论】:

  • 很抱歉,我以为我已经发布了该版本的代码。我尝试使用 as!,但这并不能消除编译器错误。然后我尝试将其删除,必须将其粘贴到我上面的问题中。我编辑了我原来的问题,但错误仍然存​​在。
  • 没问题,它发生了。 :) 但这确实是错误,请参阅我的 Playground 的 screenshot。如果它仍然失败,这意味着除了这个 sn-p 代码之外还有其他地方存在问题。
  • 好的,首先感谢 TON 发布您的代码图片。它比我尝试的要简单得多(我已经研究了几个小时,所以它最终变得复杂),并且简单的版本可以工作。
猜你喜欢
  • 1970-01-01
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 2017-07-01
  • 2016-01-12
相关资源
最近更新 更多