我知道如何从单个函数中创建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!” (因此解包可选值)不能引发异常,即:)
答案 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"])
}