无法将NSDictionary类型的值指定为NSDictionary类型的值

时间:2015-07-17 20:20:28

标签: swift nsdictionary nsjsonserialization swift2

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
        }

2 个答案:

答案 0 :(得分:2)

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

  

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

do catch仅处理并且仅(重新)抛出错误。没有其他的。如果您强制解包可选的nil,则您将收到EXC_BAD_INSTRUCTION fatal 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尝试从可选中获取值,如果成功,则展开的值存储在data中,否则会引发MyError.ParsingFailed
  • weatherData = ...仅在前一个guard语句成功时执行,
    • 它尝试从数据创建JSON对象,如果失败,则抛出错误,
    • 如果成功,它会尝试将其投放到NSDictionaryas?),如果这也成功,weatherData包含您的NSDictionary,否则MyError.ParsingFailed抛出

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

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

NSData(contentsOfURL:options:)也不是个好主意。这是同步调用,因此,它将阻止您的主线程(应用程序看起来像冻结),直到请求失败或成功。

答案 1 :(得分:0)

您可以使用NSDictionary强制演员!(但最好使用&#34;警卫&#34;比如@ robertvojta&#39;答案)。< / p>

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

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

Playground screenshot

编辑:关注@ robertvojta的回答和解释,我已经编辑了我关于Swift 2的错误断言并强行施放&#34; do ... catch&#34;。此外,请注意,在屏幕截图中,NSData仅用于在Playground中进行快速测试。