在 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)?的主要内容,如果未能解决你的问题,请参考以下文章