1

这个 stackoverflow question中,建议将类型[AnyObject]转换为类型化数组,但在我的情况下,返回值是单数AnyObject向下转换为单数JSONObjectWithData

// 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
     }
}

如何让 Swift 自动解包jsonResult

更新:这是一个更好的例子来说明问题:

func intOrThrow(arg: Int) throws -> AnyObject? {
    if arg < 0 {
        throw NSError(domain: "test", code: 400, userInfo: nil)
    } else if arg == 0 {
        return ["ZERO"]
    } else if arg > 1000 {
        return nil
    }
    return arg * 2
}

func strOrNil(arg: Int) -> String? {
    if arg < 0 ||  arg > 1000 {
        return nil
    }
    return "NUMBER\(arg)"
}

print("before intOrThrow(100) and optional unwrap")
if let x = try? self.intOrThrow(100) as? [String], // incorrect type
results = x?.count {
    print("count is \(results). x is \(x)")
}
print("before intOrThrow(0) and optional unwrap")
if let x = try? self.intOrThrow(0) as? [String], // good type
results = x?.count {
    print("count is \(results). x is \(x)")
}
print("before intOrThrow(-100) and optional unwrap")
if let x = try? self.intOrThrow(-100) as? [String], // throw
results = x?.count {
    print("count is \(results). x is \(x)")
}
print("before intOrThrow(1111) and optional unwrap")
if let x = try? self.intOrThrow(1111) as? [String], // nil
results = x?.count {
    print("count is \(results). x is \(x)")
}

print("before intOrThrow(200) and block")
if let x = try? self.intOrThrow(200) as? [String] { // incorrect type
    print("count is \(x?.count). x is \(x)") // still require ! or ?, else compile error
}
print("before intOrThrow(0) and block")
if let x = try? self.intOrThrow(0) as? [String] { // good type
    print("count is \(x?.count). x is \(x)") // still require ! or ?, else compile error
}
print("before intOrThrow(-200) and block")
if let x = try? self.intOrThrow(-200) as? [String] { // throw
    print("count is \(x!.count). x is \(x)") // still require ! or ?, else compile error
}
print("before intOrThrow(2222) and block")
if let x = try? self.intOrThrow(2222) as? [String] { // nil
    print("count is \(x?.count). x is \(x)") // still require ! or ?, else compile error
}
print("done intOrThrow")

print("before strOrNil(3333) and block")
if let x = self.strOrNil(2222) { // nil, no type cast
    print("count is \(x.lowercaseString). x is \(x)") // don't require ! or ?
}
print("done strOrNil")
输出:
    在 intOrThrow(100) 和可选展开之前
    在 intOrThrow(0) 和可选展开之前
    计数为 1。x 是可选的(["ZERO"])
    在 intOrThrow(-100) 和可选展开之前
    在 intOrThrow(1111) 和可选展开之前
    在 intOrThrow(200) 之前并阻止
    计数为零。x 为零
    在 intOrThrow(0) 之前并阻塞
    计数是可选的(1)。x 是可选的([“零”])
    在 intOrThrow(-200) 之前并阻止
    在 intOrThrow(2222) 之前并阻止
    计数为零。x 为零
    完成 inOrThrow
    在 strOrNil(3333) 和块之前
    完成 strOrNil
4

1 回答 1

0

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

让我们从try?. try?和plain old之间的区别在于trytry?要么成功要么返回nil,而try承诺它会成功或抛出一些错误。这样做是改变返回类型,在这种情况下JSONObjectWithData从返回AnyObjectAnyObject?.

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语句中,您可以解包一个变量,如果它通过,则在解包链中使用它,就像我的guard语句如何首先解包data然后jsonResult使用包装的数据,依此类推。

于 2015-11-01T01:47:42.023 回答