web-dev-qa-db-ja.com

条件付きバインディングのイニシャライザーは、 'AnyObjectではなくオプションの型である必要があります-アプローチ

次のコードは、「条件付きバインディングの初期化子は、「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 checktype 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

}
10
NNikN

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()
9
R Menke

あなたは探している as?、左側のものを右側の型に変換しようとし、変換が不可能な場合はnilを返します。

let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments)

if let actualDetails = details as? NSDictionary {
    print("Parse Data")
}

SwiftでisKindOfClassを使用する必要はめったにありません。使用していることに気付いた場合は、その理由を尋ね、asまたはas?代わりに機能します。

1
Paul Cantrell