В этом вопросе о переполнении стека рекомендуется ввести cast [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")
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