次のコードは、「条件付きバインディングの初期化子は、「AnyObject」ではなく、オプションの型である必要があります」というメッセージをスローします。
func parseData2(){
var data:NSData?
if let data2 = data {
do {
let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments)
if let actualDetails = details where actualDetails.isKindOfClass(NSDictionary) {
print("Parse Data")
}
}catch {
print("Error \(error)")
}
}
}
上記のエラーを解決するために、次のコードを使用しました。
func parseData2(){
var data:NSData?
if let data2 = data {
do {
let details:AnyObject = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments)
if let actualDetails:AnyObject = details where actualDetails.isKindOfClass(NSDictionary) {
print("Parse Data")
}
}catch {
print("Error \(error)")
}
}
}
上記よりも良いアプローチはありますか、それとも私のコードがクラッシュする可能性がありますか?
nil check、type checkそしてtype cast checkを考慮して、追加したいコードがもう1つあります。その背後にある理由Swiftは優れた柔軟性を提供しますが、問題を修正するのは少し難しいです。辞書があるとしましょうcityDetailsそして私は自分でデータを取得しようとしています。オプションのcityZipCodeおよびself.cityIdentifierは、var cityZipCode:Int?およびvar cityIdentifier:Int?として定義されます。
if let cityBasic = cityDetails["basicDetails"] where
cityBasic!.isKindOfClass(NSDictionary) {
self.cityZipCode = (cityBasic as! NSDictionary)["Zip"].integerValue ?? 0
self.cityIdentifier = (cityBasic as! NSDictionary)["cityId"].integerValue ?? 0
}
try
から結果をアンラップする必要はありません。これはオプションではありません。結果をtry
からNSDictionary
にキャストする必要があります。使用する as?
それをダウンキャストします。
ベストプラクティス:適切なエラー処理のために返されたエラーへのフルアクセス
func parseData2(){
var data:NSData?
if let data2 = data {
do {
let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments)
if let detailsDict = details as? NSDictionary {
print("Parse Data")
} else if let detailsArray = details as? NSArray {
print("array")
}
} catch {
print("Error \(error)")
}
}
}
迅速で汚い:エラー処理は私には向いていません!
func parseData2(){
var data:NSData?
if let data2 = data {
let details = try? NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments)
if let detailsDict = details as? NSDictionary {
print("Parse Data")
} else {
print("details might be nil, or not an NSDictionary")
}
}
}
悪いお尻モード:クラッシュは機能です
func parseData2(){
var data:NSData?
if let data2 = data {
let details = try! NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) as! NSDictionary
}
}
複数のアンラップに関する追加情報:以下のコードを遊び場にドロップしてください。
struct SomeStruct {
var anOptional : Int?
init() {
}
}
func unwrapWithIfLet() {
if let unWrappedStruct = myStruct, let unWrappedSomething = unWrappedStruct.anOptional {
print("multiple optional bindings succeeded")
// both unWrappedStruct and unWrappedSomething are available here
} else {
print("something is nil")
}
}
func unwrapWithGuard() {
guard let unWrappedStruct = myStruct, let unWrappedSomething = unWrappedStruct.anOptional else {
print("something is nil")
return
}
print("multiple optional bindings succeeded")
// both unWrappedStruct and unWrappedSomething are available here
}
var myStruct : SomeStruct?
//unwrapWithGuard()
//unwrapWithIfLet()
myStruct = SomeStruct()
myStruct!.anOptional = 1
unwrapWithGuard()
unwrapWithIfLet()
あなたは探している as?
、左側のものを右側の型に変換しようとし、変換が不可能な場合はnilを返します。
let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments)
if let actualDetails = details as? NSDictionary {
print("Parse Data")
}
SwiftでisKindOfClass
を使用する必要はめったにありません。使用していることに気付いた場合は、その理由を尋ね、as
またはas?
代わりに機能します。