【问题标题】:Establish Error Case in NSURLConnection, JSON Parsing in Swift在 NSURLConnection 中建立错误案例,在 Swift 中解析 JSON
【发布时间】:2014-11-08 14:33:22
【问题描述】:

我正在尝试从我网站上的 JSON 中提取信息。这样做时,如果连接出现错误,它应该返回该错误并将其记录到控制台。我遇到的问题是,如果我打开飞机更多或失去信号,错误:fatal error: unexpectedly found nil while unwrapping an Optional value 使应用程序崩溃。当我为简单地记录错误设置条件时,为什么它会返回这个?提前谢谢!

我不确定为什么没有记录错误并阻止应用程序崩溃。任何指针都会有所帮助。

JSONLoader.swift

import Foundation

var arrayOfMeals: [Meal] = [Meal]()
var weekDayArray = ["monday"]


func getJSON(urlToRequest: String) -> NSDictionary {

    var url: NSURL = NSURL(string: urlToRequest)!
    var jsonRequest: NSURLRequest = NSURLRequest(URL: url)
    var jsonResponse: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil

    var error: NSError?
    var dataValue: NSData =  NSURLConnection.sendSynchronousRequest(jsonRequest, returningResponse: jsonResponse, error:&error)!

    if error? == nil {
        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataValue, options: NSJSONReadingOptions.MutableContainers , error: &error) as NSDictionary
        NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
        if error? == nil {
            return jsonResult
        }
        else {
            return NSDictionary(object: "Error: Something with parsing went wrong :(", forKey: "error")
        }
    }
    else {
        return NSDictionary(object: "Error: There was an error with your connection :(", forKey: "error")
    }

}

func loadJSON(jsonDictionary: NSDictionary) {

    for days in weekDayArray{
        var resultsArray = jsonDictionary[days] as NSArray
        for obj: AnyObject in resultsArray{
            let breakfast = (obj.objectForKey("breakfast")! as String)
            let lunch = (obj.objectForKey("lunch")! as String)
            let dinner = obj.objectForKey("dinner")! as String
            let dateString = obj.objectForKey("dateString")! as String
            let dayOfWeek = obj.objectForKey("dayOfWeek")! as String
            let newMeal = Meal(breakfast: breakfast, lunch: lunch, dinner: dinner, dayOfWeek: dayOfWeek, dateString: dateString)
            if theDays(newMeal.dateString) >= 0 {
                arrayOfMeals.append(newMeal)
            }
        }
    }


}

我希望函数 getJSON 建立到站点的 NSURLConnection,解析 JSON 日期,并返回一个 NSDictionary。如果连接中存在错误,则建立错误案例,然后返回字典,其中包含解释错误的值。解析 JSON 文件时会发生额外的错误情况,并返回具有类似错误的 NSDictionary。

我希望函数 loadJSON 能够创建对象 Meal 的实例,我将其定义为具有早餐、午餐、晚餐、日期和星期几的属性。这个实例的值是函数getJSON返回的NSDictionary的结果。如果这一天是未来,请将其附加到我的arrayOfMeals。否则,忽略该实例。

MealViewController

override func viewDidLoad() {
    super.viewDidLoad()

    var req = getJSON("http://www.seandeaton.com/meals/Mealx")
    loadJSON(req)


}

MealModel.swift - 创建餐点实例

class Meal {

    let breakfast: String
    let lunch: String
    let dinner: String
    let dayOfWeek: String
    let dateString: String

    init(breakfast: String, lunch: String, dinner: String, dayOfWeek: String, dateString: String) {

        self.breakfast = breakfast
        self.lunch = lunch
        self.dinner = dinner
        self.dayOfWeek = dayOfWeek
        self.dateString = dateString

    }

}

如何防止应用在建立连接失败并将错误消息记录到控制台时崩溃?再次感谢。

【问题讨论】:

    标签: ios json swift


    【解决方案1】:

    关键的观察是,在调用 sendSynchronousRequest 时,您正在检索 NSData,您已将 NSData 定义为不是可选的,并且您附加了一个 !,这将强制展开可选的返回值。因此,如果可选的NSData 是nil(如果有任何网络问题就会发生这种情况),则此代码将失败。

    相反,您应该简单地将NSData 保留为可选项(即NSData?)并在尝试解包之前检查它是否为nil。因此,我可能会提出类似的建议:

    func retrieveJSON(urlToRequest: String) -> NSDictionary {
    
        let url: NSURL = NSURL(string: urlToRequest)!
        let jsonRequest: NSURLRequest = NSURLRequest(URL: url)
    
        var jsonResponse: NSURLResponse?
        var error: NSError?
        let dataValue = NSURLConnection.sendSynchronousRequest(jsonRequest, returningResponse: &jsonResponse, error:&error)
    
        if dataValue != nil {
            if let jsonResult = NSJSONSerialization.JSONObjectWithData(dataValue!, options: .MutableContainers, error: &error) as? NSDictionary {
                return jsonResult
            } else {
                return [
                    "error": "Error: Something with parsing went wrong :(",
                    "localizedDescription": error?.localizedDescription ?? ""
                ];
            }
        }
        else {
            return [
                "error": "Error: There was an error with your connection :(",
                "localizedDescription": error?.localizedDescription ?? ""
            ];
        }
    }
    

    以上内容将修复因强制解包可选的NSData 而导致的崩溃,如果出现网络问题,该选项将是nil。请注意,您没有向我们展示调用getJSON 然后随后调用loadJSON 的代码,但我假设您正在那里进行必要的错误处理检查。

    注意,我还取消了尴尬的 AutoreleasingUnsafeMutablePointer&lt;NSURLResponse?&gt; 构造。我还将错误的localizedDescription 添加到返回的字典中。

    就个人而言,我通常会返回完整的NSError 对象和NSURLResponse 对象,以便调用者可以诊断出错误的确切性质,而不仅仅是文本描述。


    在对您的代码进行更彻底的修改时,我建议您通常避免同步请求。永远不要从主线程执行同步请求。

    例如,您可以定义异步执行请求的方法,如下所示:

    func retrieveJSON(urlToRequest: String, completionHandler:(responseObject: NSDictionary?, error: NSError?) -> ()) {
    
        let url: NSURL = NSURL(string: urlToRequest)!
        let jsonRequest: NSURLRequest = NSURLRequest(URL: url)
    
        var jsonResponse: NSURLResponse?
        NSURLConnection.sendAsynchronousRequest(jsonRequest, queue: NSOperationQueue.mainQueue()) {
            response, data, error in
    
            if data == nil {
                completionHandler(responseObject: nil, error: error)
            } else {
                var parseError: NSError?
                let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &parseError) as NSDictionary?
                completionHandler(responseObject: jsonResult, error: error)
            }
        }
    }
    

    然后您可以使用“尾随闭包语法”来调用它,如下所示:

    retrieveJSON(urlString) {
        responseObject, error in
    
        if responseObject == nil {
            // handle error here, e.g.
    
            println(error)
            return
        }
    
        // handle successful the `NSDictionary` object, `responseObject`, here
    }
    
    // but don't try to use the object here, because the above runs asynchronously
    

    【讨论】:

    • 非常感谢您的回答 - 我正在使用retrieveJSON 实现您回答的后半部分。您提到不使用闭包中的对象,因为它是异步运行的。这有什么特别不好的?此外,我是否应该简单地返回 NSDictionary 的内容以在其他地方实施?抱歉有这些问题。我已经在应用程序中使用 JSON 文件进行了处理,但必须请求数据引入了一组我试图熟悉的全新功能。再次感谢你,罗伯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2021-04-05
    相关资源
    最近更新 更多