尝试在Swift 2中捕获整个块

时间:2016-02-02 22:00:59

标签: ios swift swift2

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

让我举个简单的例子。这是来自Facebook图形api for / 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!” (因此解包可选值)不能引发异常,即:)

2 个答案:

答案 0 :(得分: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失败。你必须特别期待和防范这种可能性,这正是防守发挥作用的可能性,可能与投掷相结合。

答案 1 :(得分:0)

要更轻松地从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"])
}