由于展开,网络呼叫失败

时间:2015-05-15 09:45:21

标签: ios swift cocoa-touch nsdictionary

这是我对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

有关
  

致命错误:在解包可选值时意外发现nil

我正在展开dataObject,那么可能是什么问题?

1 个答案:

答案 0 :(得分:3)

你真的,真的,需要摆脱强行解缠的习惯。如果你得到一个可选项,你只需用!打开它,就会永远遇到这些问题。

以下是内部代码的一个版本,用于检查每个回合的选项:

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将关闭类型)。 / p>

是的,有时你肯定知道一个值不会是零,所以只需要强行打开它就会更容易和更清洁(例如用你的NSURL - 你可以非常安全地使用那个因为没有涉及用户输入。)

但是直到你不断地对抗零值错误,你最好以这种方式编写你的代码。

在处理选项后,explore the other techniques编写更整洁的代码会更加舒适。

您可能还想在处理JSON结果时考虑使用更强的类型,例如,您可以执行以下操作:

if let weatherDictionary = weatherObj as? [String:AnyObject]

等处理字典内部时。同样,如果您信任forecast.io始终以完全正确的形式提供有效的JSON数据,您可以跳过此步骤并强制执行所有操作,但在编写代码时将更难调试,并且您冒着代码冒险的风险在生产中(而不是优雅地失败)如果你得到了腐败的数据。