在 Swift (2.0) 中正确处理 NSJSONSerialization (try catch)?

Posted

技术标签:

【中文标题】在 Swift (2.0) 中正确处理 NSJSONSerialization (try catch)?【英文标题】:Correct handling of NSJSONSerialization (try catch) in Swift (2.0)? 【发布时间】:2015-07-08 15:03:16 【问题描述】:

arowmy init 在 Swift Call can throw, but it is not marked with 'try' and the error is not handled let anyObj = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject] 收到一条错误消息。我认为就我而言,我不能使用 try catch 块,因为此时 super 尚未初始化。 “尝试”需要一个抛出的函数。

这是我的功能:

required init(coder aDecoder : NSCoder)

    self.name  = String(stringInterpolationSegment: aDecoder.decodeObjectForKey("name") as! String!)
    self.number = Int(aDecoder.decodeIntegerForKey("number"))
    self.img = String(stringInterpolationSegment: aDecoder.decodeObjectForKey("image") as! String!)
    self.fieldproperties = []

    var tmpArray = [String]()
    tmpArray = aDecoder.decodeObjectForKey("properties") as! [String]


    let c : Int = tmpArray.count
    for var i = 0; i < c; i++
    
        let data : NSData = tmpArray[i].dataUsingEncoding(NSUTF8StringEncoding)!

         // Xcode(7) give me error: 'CAll can thorw, but it is not marked with 'try' and the error is not handled'
        let anyObj =  NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]

        let label = anyObj["label"] as AnyObject! as! String
        let value = anyObj["value"] as AnyObject! as! Int
        let uprate = anyObj["uprate"] as AnyObject! as! Int
        let sufix = anyObj["sufix"] as AnyObject! as! String

        let props = Fieldpropertie(label: label, value: value, uprate: uprate, sufix: sufix)
        self.fieldproperties.append(props)
    

Xcode 的意思是: let anyObj = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]

但我不知道在这里根据这个文档做正确的想法https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html

【问题讨论】:

请阅读全文,而不仅仅是您认为重要的部分。你已经有了一个“抛出的函数”——NSJSONSerialization.JSONObjectWithData @Rob 是的,我的意思是 Swift 2.0。 投了反对票,因为示例代码对以前的方法和示例没有用处。 @NathanMcKasklei 不明白你的意思。该代码描述了我的问题。 【参考方案1】:

jsonObject 可以出现throw 错误,因此将其放在do 块中,使用trycatch 引发的任何错误。在 Swift 3 中:

do 
    let anyObj = try JSONSerialization.jsonObject(with: data) as! [String: Any]

    let label = anyObj["label"] as! String
    let value = anyObj["value"] as! Int
    let uprate = anyObj["uprate"] as! Int
    let sufix = anyObj["sufix"] as! String

    let props = Fieldpropertie(label: label, value: value, uprate: uprate, sufix: sufix)

    // etc.
 catch 
    print("json error: \(error.localizedDescription)")

或者,在 Swift 4 中,您可以通过使 struct 符合 Codable 来简化代码:

struct Fieldpropertie: Codable 
    let label: String
    let value: Int
    let uprate: Int
    let suffix: String

然后

do 
    let props = try JSONDecoder().decode(Fieldpropertie.self, from: data)
    // use props here; no manual parsing the properties is needed
 catch 
    print("json error: \(error.localizedDescription)")

对于 Swift 2,请参阅 previous revision of this answer。

【讨论】:

哦,谢谢。它工作正常。我不知道为什么我没有这样做;) @SaumilShah,见编辑:catch let error1 as NSError print("json error: (error1.localizedDescription)") 我试过了,但 Xcode 说 create throw....你能分享一下带 throw 的句柄的例子吗? @SaumilShah - 我们可以向您展示如何投掷,但最好只参考The Swift Programming Languages: Error Handling。或者使用reproducible 收到的错误示例创建您自己的问题。 非常感谢您的支持【参考方案2】:

JSONSerialization.JSONObject 抛出 ErrorType 而不是 NSError。

所以正确的捕获是

do 
    let anyObj = try JSONSerialization.JSONObject(with: data, options: []) as! [String:AnyObject]
    // use anyObj here
 catch let error 
    print("json error: \(error)")

catch let errorerror 的类型是ErrorType

【讨论】:

根据文档JSONObjectWithData会抛出一个NSError,它符合ErrorType。 是的,这就是文字所说的。编码合约显示 ErrorType。当您在闭包中执行此操作并且不遵守编码合同时,您将得到非常难以理解的错误。当你只捕获 NSError 时,编译器必须假设还有未捕获的情况,这可能会导致上下文出现问题。 localizedDescription 没有为 ErrorType 定义。我在let error as ErrorType 线上有一条警告说测试总是正确的。 你是对的,ErrorTypelet error as ErrorType 中是多余的,并且它没有本地化描述。并且它没有本地化描述。我会在这里修正我的答案。【参考方案3】:

不知道能不能解决你的问题,方法不就是JSONObjectWithData:options:error:吗?我认为您缺少 error 参数。

【讨论】:

不,在 Swift 2.0 中,您拥有新的 try-catch 机制,JSONObjectWithData 现在不使用 error 参数,而是抛出错误。 @Rob 啊,我明白了。问题是 Swift 1.2,这是我正在使用的,所以我认为这可能是问题所在。

以上是关于在 Swift (2.0) 中正确处理 NSJSONSerialization (try catch)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 2.0 中获得正确的 UIView 大小或边界?

Swift 2.0 异常处理

Swift 2.0 异常处理

处理 Swift 2.0 中的转换错误

尝试在 swift 2.0 中执行 GET 请求时出错

从 iOS 9 / Swift 2.0 发送 HTTP POST 请求时,PHP 服务器没有收到正确的数据