无法将 NSDictionary 类型的值分配给 NSDictionary 类型的值
Cannot assign value of type NSDictionary to a value of type NSDictionary
Swift 2.0 (Xcode 7 Beta 3),据我所知语法看起来很棒。我之前获得了一个 JSON 字符串,然后当我尝试解析它时,我在 "try NSJSONSerialization" 行的 "as" 关键字上得到了上述错误。我做错了什么?感谢您的回答。
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
}
您可以使用 !
强制转换为 NSDictionary
(但最好像@robertvojta 的回答那样使用 "guard")。
此外,您可以使用 []
代替 MutableContainers
:
weatherData = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! NSDictionary
编辑:根据@robertvojta 的回答和解释,我已经删除了我关于 Swift 2 和在 "do ... catch" 内强制转换的错误断言。另外,请注意,在屏幕截图中,NSData 当然只是用于在 Playground 中进行快速测试。
@EricD 在他的回答中写的是错误的。引用:
With Swift 1.2 using ! was dangerous and it was better to use Optional
binding (if let ...) but in Swift 2 when you handle the errors with do
catch, you can actually use ! (but one should not forget to use a
generic catch, like you do, in addition to possible other specific
error handling).
do catch
只处理并且只处理(重新)抛出的错误。没有其他的。如果您强制解包可选 nil
,您将收到 EXC_BAD_INSTRUCTION
和 fatal error: unexpectedly found nil while unwrapping an Optional value
。即使您的代码包含在 do catch
中,您也会得到它。像 throws
、catch
这样的关键字可以让人联想到它是关于异常的,但它不是——只是错误。同样适用于 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 写的东西。使用 as!
和 !
仍然是危险的 即使在 Swift 2.
NSData(contentsOfURL:options:)
也不是好主意。这是同步调用,因此,它将阻塞您的主线程(应用程序看起来像冻结了),直到请求失败或成功。
Swift 2.0 (Xcode 7 Beta 3),据我所知语法看起来很棒。我之前获得了一个 JSON 字符串,然后当我尝试解析它时,我在 "try NSJSONSerialization" 行的 "as" 关键字上得到了上述错误。我做错了什么?感谢您的回答。
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
}
您可以使用 !
强制转换为 NSDictionary
(但最好像@robertvojta 的回答那样使用 "guard")。
此外,您可以使用 []
代替 MutableContainers
:
weatherData = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! NSDictionary
编辑:根据@robertvojta 的回答和解释,我已经删除了我关于 Swift 2 和在 "do ... catch" 内强制转换的错误断言。另外,请注意,在屏幕截图中,NSData 当然只是用于在 Playground 中进行快速测试。
@EricD 在他的回答中写的是错误的。引用:
With Swift 1.2 using ! was dangerous and it was better to use Optional binding (if let ...) but in Swift 2 when you handle the errors with do catch, you can actually use ! (but one should not forget to use a generic catch, like you do, in addition to possible other specific error handling).
do catch
只处理并且只处理(重新)抛出的错误。没有其他的。如果您强制解包可选 nil
,您将收到 EXC_BAD_INSTRUCTION
和 fatal error: unexpectedly found nil while unwrapping an Optional value
。即使您的代码包含在 do catch
中,您也会得到它。像 throws
、catch
这样的关键字可以让人联想到它是关于异常的,但它不是——只是错误。同样适用于 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 写的东西。使用 as!
和 !
仍然是危险的 即使在 Swift 2.
NSData(contentsOfURL:options:)
也不是好主意。这是同步调用,因此,它将阻塞您的主线程(应用程序看起来像冻结了),直到请求失败或成功。