网络调用因展开而失败
Network call fails due to unwrapping
这是我对 forecast.io
进行网络调用的代码。
在 ViewController
我有:
private let apiKey = ""//my key
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)")
let forecastURL = NSURL(string: "37.8267,-122.423", relativeToURL : baseURL)
let sharedSession = NSURLSession.sharedSession()
let downloadTask : NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary : NSDictionary = NSJSONSerialization.JSONObjectWithData(
dataObject!, options: nil, error: nil) as! NSDictionary
}
})
downloadTask.resume()
}
我正在尝试将我的数据设置为 NSDictionary
以便能够访问它。我有一个与 weatherDictionary
:
有关的错误(绿线)
fatal error: unexpectedly found nil while unwrapping an Optional value
我正在打开 dataObject
,所以可能是什么问题?
你真的,真的,需要改掉强制展开的习惯。如果每当你得到一个可选的,你只是使用 !
来打开它,你将永远遇到这些问题。
这是你的内部代码的一个版本,它在每个回合检查可选值:
let sharedSession = NSURLSession.sharedSession()
let downloadTask = sharedSession.downloadTaskWithURL(forecastURL!)
{ location, response, error in
if let error = error {
// log error
}
else if let dataObject = NSData(contentsOfURL: location) {
let weatherObj: AnyObject? = NSJSONSerialization.JSONObjectWithData(
dataObject, options: nil, error: nil)
if let weatherDictionary = weatherObj as? NSDictionary {
}
else {
// log error with conversion of weather to dictionary
}
}
else {
// log error with dataObject
}
}
是的,这写起来更长也更烦人(不过,类型推断会帮助你走另一条路——你不必显式地键入所有内容,例如在回调中,IMO 更清楚地忽略类型) .
是的,有时你肯定知道一个值不会为零,所以强制解包它更容易和更清晰(例如,使用你的 NSURL
- 你可以很安全地使用那个只要不涉及用户输入)。
但在你不bash你的脑袋经常出现空值错误之前,最好以这种方式编写你的代码。
一旦您对处理可选值更加自如, 可以编写更整洁的代码。
您可能还想考虑在处理 JSON 结果时使用更强的类型,例如,您可以执行以下操作:
if let weatherDictionary = weatherObj as? [String:AnyObject]
处理字典内部时依此类推。同样,如果您相信 forecast.io
总是以完全正确的形式为您提供有效的 JSON 数据,您可以跳过这一步并强制执行所有操作,但在编写代码时这将更难调试,并且您有风险如果您取回损坏的数据,您的代码会在生产环境中崩溃(而不是优雅地失败)。
这是我对 forecast.io
进行网络调用的代码。
在 ViewController
我有:
private let apiKey = ""//my key
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)")
let forecastURL = NSURL(string: "37.8267,-122.423", relativeToURL : baseURL)
let sharedSession = NSURLSession.sharedSession()
let downloadTask : NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary : NSDictionary = NSJSONSerialization.JSONObjectWithData(
dataObject!, options: nil, error: nil) as! NSDictionary
}
})
downloadTask.resume()
}
我正在尝试将我的数据设置为 NSDictionary
以便能够访问它。我有一个与 weatherDictionary
:
fatal error: unexpectedly found nil while unwrapping an Optional value
我正在打开 dataObject
,所以可能是什么问题?
你真的,真的,需要改掉强制展开的习惯。如果每当你得到一个可选的,你只是使用 !
来打开它,你将永远遇到这些问题。
这是你的内部代码的一个版本,它在每个回合检查可选值:
let sharedSession = NSURLSession.sharedSession()
let downloadTask = sharedSession.downloadTaskWithURL(forecastURL!)
{ location, response, error in
if let error = error {
// log error
}
else if let dataObject = NSData(contentsOfURL: location) {
let weatherObj: AnyObject? = NSJSONSerialization.JSONObjectWithData(
dataObject, options: nil, error: nil)
if let weatherDictionary = weatherObj as? NSDictionary {
}
else {
// log error with conversion of weather to dictionary
}
}
else {
// log error with dataObject
}
}
是的,这写起来更长也更烦人(不过,类型推断会帮助你走另一条路——你不必显式地键入所有内容,例如在回调中,IMO 更清楚地忽略类型) .
是的,有时你肯定知道一个值不会为零,所以强制解包它更容易和更清晰(例如,使用你的 NSURL
- 你可以很安全地使用那个只要不涉及用户输入)。
但在你不bash你的脑袋经常出现空值错误之前,最好以这种方式编写你的代码。
一旦您对处理可选值更加自如,
您可能还想考虑在处理 JSON 结果时使用更强的类型,例如,您可以执行以下操作:
if let weatherDictionary = weatherObj as? [String:AnyObject]
处理字典内部时依此类推。同样,如果您相信 forecast.io
总是以完全正确的形式为您提供有效的 JSON 数据,您可以跳过这一步并强制执行所有操作,但在编写代码时这将更难调试,并且您有风险如果您取回损坏的数据,您的代码会在生产环境中崩溃(而不是优雅地失败)。