【问题标题】:Try catch whole block in Swift 2尝试在 Swift 2 中捕获整个块
【发布时间】:2016-05-11 21:59:30
【问题描述】:

我知道如何从单个函数中进行 try-catch。但问题是我想尝试捕获整个代码块 - 如果出现问题很简单,忽略整个代码块。

让我给你看一个简单的例子。这是来自 Facebook 图形 api 的 /me/taggable_friends 的简单解析器:

let params:[NSObject : AnyObject] = ["fields": "first_name, last_name, id, picture"]
let request = FBSDKGraphRequest(graphPath: "/me/taggable_friends", parameters: params, HTTPMethod: "GET") 
request.startWithCompletionHandler { (connection, result, error) -> Void in

            if let error = error {
                print(error)
            }
            else{

                let resultDictionary:NSDictionary! = result as! [String: AnyObject]
                let array = resultDictionary["data"] as! NSArray
                for object in array {
                    let firstName = object["first_name"] as! String
                    let lastName = object["last_name"] as! String
                    let tagId = object["id"] as! String
                    let picture = object["picture"] as! NSDictionary
                    let pictureData = picture["data"] as! NSDictionary
                    let pictureUrl = pictureData["url"] as! String

                    let friend = FacebookFriend(firstName: firstName, lastName: lastName, tagId: tagId, picture: pictureUrl)

                    print(pictureUrl)

                    self.friends.append(friend)
                }


            }
        }

该代码正在运行并且会悄悄地失败,因为错误不是零。但是假设 facebook 改变了一些东西,或者 json 中的某些值不可用。应用程序将崩溃。所以我必须为这段代码的几乎每一行都做 if-let 语句。很快它就会变得又长又难读。在java中,我只是为整个块做一个try-catch。但很快我不知道该怎么做。更重要的是编译器说“as!” (所以展开可选值)不能引发错误的异常:)

【问题讨论】:

    标签: ios swift swift2


    【解决方案1】:

    为了更容易地从 json 中获取值,您可以使用SwiftyJSON framework。在您的问题中描述的情况下,您可以获得所需的值并将其包装在 if let 条件中。例如(来自 SwiftyJSON 自述文件):

    let json = JSON(data: dataFromNetworking)
    if let userName = json[999999]["wrong_key"]["wrong_name"].string {
        //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
    } else {
        //Print the error
        print(json[999999]["wrong_key"]["wrong_name"])
    }
    

    【讨论】:

    • 很好,我去看看。
    【解决方案2】:

    这就是guard 语句派上用场的地方,基本语法是:

    guard let foo = expression else {
        handle the error, and return (or throw)
    }
    

    在这种情况下,您希望保护一堆可选解析免受 Facebook 在未来某个时候更改其 API 的变幻莫测。在这种情况下使用 guard 和 continue 可以让您安全地跳过块的其余部分:

        for object in array {
            guard
                let firstName = object["first_name"] as? String,
                let lastName = object["last_name"] as? String,
                let tagId = object["id"] as? String,
                let picture = object["picture"] as? NSDictionary,
                let pictureData = picture["data"] as? NSDictionary,
                let pictureUrl = pictureData["url"] as? String else {
                    print("JSON format has changed")
                    continue
            }
    
            let friend = FacebookFriend(firstName: firstName, lastName: lastName, tagId: tagId, picture: pictureUrl)
    
            print(pictureUrl)
    
            self.friends.append(friend)
        }
    

    一般来说,Swift 的 try/catch 块并不真正类似于其他语言中的 try/catch,尤其是对于 Java。在 Java 中,所有异常(在某种程度上)都是可处理的,即使是空引用、数组边界问题等。在 Swift 中,try/catch 错误绝对不是为了处理异常,而只是为了处理错误。所以没有办法使用 try/catch 来保护自己免受 as! String 失败的影响。您必须特别期待并防范这种可能性,这正是后卫发挥作用的地方,可能与投掷结合使用。

    【讨论】:

    • 因此,如果 json 中不存在某些键(如 first_name),基本上Guard 会阻止我的应用程序崩溃,但我仍然必须为每个键添加 if-let 吗?但如果我只添加 if-lets 会不会一样?
    • guard letif let 的替代品。除了if let foo = bar 之外,它非常相似,foo 只能在if 语句的成功部分中访问。使用guard let foo,foo 可以在包含guard let 的块的其余部分访问,因此,正如您在上面的块中看到的,您不会得到一堆嵌套的if let 块。它还具有更自然的流程,因为异常情况会立即处理,并且例程的主要流程继续有增无减。
    • 顺便说一句,guard 可以与任何条件一起使用,而不仅仅是guard let 守卫所做的是为代码块建立前提条件,该代码块必须存在才能执行该块的其余部分。所以你也可以使用guard index < array.count else { throw index out of bounds }
    猜你喜欢
    • 1970-01-01
    • 2011-08-23
    • 2021-08-27
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多