如何在 Swift 中正确获取 Do-Catch 范围之外的值(使用 Try)

Posted

技术标签:

【中文标题】如何在 Swift 中正确获取 Do-Catch 范围之外的值(使用 Try)【英文标题】:How Properly to Get the Value Outside of the Scope Do-Catch (using Try) in Swift 【发布时间】:2016-01-19 08:40:32 【问题描述】:

我正在尝试将 JSON 数据解析为字典,用于解析我使用的是单独的方法,稍后想将结果(字典)用于另一种方法中的其他操作,而不仅仅是按原样打印出来在网上的许多例子中给出,例如。 G。 here.

但是,我不能返回值,因为我被要求在 guard 中插入 return 语句,但是在插入后得到“非 void 函数应该返回一个值” .

代码如下所示:

 func  extractJSONDictionaryFrom(JSONData:NSData) ->NSMutableDictionary
    
        var dict = NSMutableDictionary()
        do 
        guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) as? NSDictionary else 
            print("Not a Dictionary")
            return
        
            dict = NSMutableDictionary(dictionary: JSON)
        
        catch let JSONError as NSError 
            print("\(JSONError)")
        
        print("The JSON is \(dict)")
        return dict
    

The approach 使用 throw 也几乎没有用,因为我需要在调用“extractJSONDictionaryFrom”时处理其他方法中的 throws

【问题讨论】:

为什么throw不好?如果方法被标记为throws 错误,那么如果你在没有do-catch 块的情况下执行JSONObjectWithData,则会抛出NSJSONSerialization 错误。但是您可以选择抛出您自己的错误(无论是自定义 ErrorType 类型,如该链接中所示,或者您自己的 NSError 对象,如果您愿意)。 但是当我调用该方法时,我需要在另一个方法中处理抛出,不是吗?我想只处理一种方法,以后避免这样做。 没关系,但是如果你不抛出错误,你必须检查nil,你不会知道它为什么失败。但是如果调用者不需要知道失败的原因,那么继续使用可选的。使用任何你想要的方法。 【参考方案1】:

一种选择是让您的方法抛出错误(无论是 NSJSONSerialization 错误,因为 JSON 解析完全失败,还是您的自定义错误,如果 JSON 解析有效,但由于某种原因它不是字典):

func extractJSONDictionaryFrom(JSONData: NSData) throws -> NSMutableDictionary 
    guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:[]) as? NSDictionary else 
        throw NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: -1, userInfo: [NSLocalizedDescriptionKey : "Not a dictionary"])
    
    return NSMutableDictionary(dictionary: JSON)

或者,另一种方法是不让它抛出错误,而是在转换失败时返回nil

func extractJSONDictionaryFrom(JSONData: NSData) -> NSMutableDictionary? 
    do 
        guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) as? NSDictionary else 
            print("Not a Dictionary")
            return nil
        
        return NSMutableDictionary(dictionary: JSON)
     catch let JSONError as NSError 
        print("\(JSONError)")
        return nil
    

我倾向于前者,但后者也有效。

【讨论】:

那(你的第二种方法)引发了另一个问题:Nil 与返回类型 'NSMutableDictionary' 不兼容 @DariusMiliauskas - 注意,正式的,如果您不想抛出错误,我建议将其更改为 NSMutableDictionary?(可选)。这样您就可以返回nil。要么使返回类型可选,要么抛出错误。这是让调用者知道 JSON 解析由于某种原因失败的两种合乎逻辑的方式。【参考方案2】:

将结果设为可选 (NSMutableDictionary?) 并使用 return nil

如果调用者不应更改返回的字典,您可能还想返回 NSDictionary?

编辑

给出的代码不起作用,因为NSJSONSerialization.JSONObjectWithData 在给定无效 JSON 的情况下会抛出错误,这会被catch 捕获。该函数返回一个空字典而不是nil。我会尝试以下方法:

func  extractJSONDictionaryFrom(JSONData:NSData) ->NSMutableDictionary?

    var dict = NSMutableDictionary()
    do 
        guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) as? NSDictionary else 
            print("Not a Dictionary")
            return nil
        
        dict = NSMutableDictionary(dictionary: JSON)
    
    catch let JSONError as NSError 
        print("\(JSONError)")
        return nil
    
    print("The JSON is \(dict)")
    return dict

我也相信传播异常会更好。

或者,您可以为所有错误返回一个空字典而不使用可选结果,但这“隐藏”错误可能是个坏主意。

【讨论】:

错误:Nil 与返回类型“NSMutableDictionary”不兼容 我不确定在这种情况下“不兼容”是什么意思。

以上是关于如何在 Swift 中正确获取 Do-Catch 范围之外的值(使用 Try)的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的“do-catch”语句执行四次?

在一个 catch 块中处理多个 swift 错误

Swift 中的复杂 JSON。如何正确获取数据。不同的结构

如何使用 swift 和 firebase 正确使用完成处理程序?

无法获取 QR 码的正确坐标,ARKit - Swift

如何从 Swift 2.0 中获取子数组