1

このスタックオーバーフローの質問では、型指定された配列にキャストすることをお勧めし[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) およびオプションの unwrap の前
    intOrThrow(0) およびオプションの unwrap の前
    count は 1 です。x は Optional(["ZERO"]) です。
    intOrThrow(-100) およびオプションのアンラップの前
    intOrThrow(1111) およびオプションの unwrap の前
    intOrThrow(200) およびブロックの前
    カウントはゼロです。xはゼロです
    intOrThrow(0) およびブロックの前
    count は Optional(1) です。x は Optional(["ZERO"]) です
    intOrThrow(-200) およびブロックの前
    intOrThrow(2222) およびブロックの前
    カウントはゼロです。xはゼロです
    intOrThrow
    strOrNil(3333) およびブロックの前
    行われた strOrNil
4

1 に答える 1

0

ここで変更したいことがいくつかあります。なぜ私が個人的に変更するのかを説明します。

から始めましょうtry?try?と普通の古いものの違いは、成功するか戻るかのどちらかtryですが、成功するかエラーをスローすることを約束します。それは、戻り値の型を変更することです。この場合は、戻り値から に戻ります。try?niltryJSONObjectWithDataAnyObjectAnyObject?

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 
}

これで 1 つのステートメントになり、問題なくコンパイルされ、3 つのオプションすべてが 1 つのステートメントでアンラップされます。guardステートメントが合格すると、、datajsonResultおよびresultsがすべて入力されます。いずれかが失敗すると、else が呼び出され、ステートメントが返されます。guardステートメントとステートメントでは、変数のラップを解除し、それが合格した場合は、ステートメントが最初にラップを解除してから、ラップされたデータを使用するように、それif letをアンラップのチェーンで使用することができます。guarddatajsonResult

于 2015-11-01T01:47:42.023 に答える