swift if-let没有打开可选的NSDictionary

时间:2015-10-31 23:14:22

标签: ios swift optional unwrap

this stackoverflow question中,建议是将类型转换[AnyObject]输入到类型化数组,但在我的情况下,返回值是单个AnyObject向下转换为单数{{1 }}:

JSONObjectWithData

如何让Swift自动解包// ObjC def: public class func JSONObjectWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> AnyObject if let jsonResult = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary { if let results = jsonResult!["results"] as? NSArray { // ! needed or compile error } }

更新:以下是显示问题的更好示例:

jsonResult
outputs:
    before intOrThrow(100) and optional unwrap
    before intOrThrow(0) and optional unwrap
    count is 1. x is Optional(["ZERO"])
    before intOrThrow(-100) and optional unwrap
    before intOrThrow(1111) and optional unwrap
    before intOrThrow(200) and block
    count is nil. x is nil
    before intOrThrow(0) and block
    count is Optional(1). x is Optional(["ZERO"])
    before intOrThrow(-200) and block
    before intOrThrow(2222) and block
    count is nil. x is nil
    done intOrThrow
    before strOrNil(3333) and block
    done strOrNil

1 个答案:

答案 0 :(得分:0)

所以我在这里发生了一些事情,我会改变,并且我会解释为什么我个人会做的不同。

让我们从try?开始。 try?与普通try之间的区别在于try?将成功或返回nil,而try承诺会成功或抛出一些错误。这样做会改变返回类型,在这种情况下,JSONObjectWithData会从返回AnyObject变为AnyObject?

do {
    let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, .MutableContainers)
} catch {} //catch and report on the error

这样,如果没有抛出错误,jsonResult保证以AnyObject存在。然后你可以做if let jsonResult = jsonResult["results"] as? NSArray。 顺便说一句,如果你可以帮助我,我就不会使用NSArray,尽可能地坚持使用Swift原生类型(像as? [AnyObject]这样的东西很好)。

现在您的代码如下所示:

var data: NSData! = NSData(base64EncodedString: "SGVsbG8gd29ybGQh", options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
    if let results = jsonResult["results"] as? [AnyObject] {
        print(results)
    } else {
        print("how did this happen?")
    }
} catch {

}

注意:您也不需要向[AnyObject]投降以进行编译,但results将为AnyObject

现在我在这种情况下并不是do catch的忠实粉丝。一个更好的方式去做这个imo是:

guard let data = NSData(base64EncodedString: "SGVsbG8gd29ybGQh", options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters),
    jsonResult = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers),
    result = jsonResult["results"] as? [AnyObject] else {
    return 
}

现在它是一个声明,编译得很好,所有三个选项都在一个声明中打开。如果guard语句通过,则datajsonResultresults都会被填充。如果有任何失败,将调用else并返回语句。在guard语句和if let语句中,您可以解包变量,如果它已通过,请在unwraps链中使用它,就像我的guard语句首次展开{{1}一样然后使用包装数据的data,依此类推。