条件绑定的初始化程序必须具有可选类型,而不是'AnyObject - Approach

时间:2021-04-25 17:05:13

The following code throws a message which says "Initializer for conditional binding must have Optional type, not '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)")
            }
        }

    }

To resolve the above error I used the following code.

为解决上述错误,我使用了以下代码。

    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)")
            }
        }

    }

Is there any better approach then the above or my code might crash?

有没有比上面更好的方法或我的代码可能会崩溃?

There is one more code which I want to add considering nil check,type check and then type cast check. The reason behind that Swift offers great flexibility but litle bit difficult to fix issues. Let's say I have a dictionary, cityDetails and I am trying to get data for self.cityZipCode and self.cityIdentifier, which are optional, defined as var cityZipCode:Int? and var cityIdentifier:Int?

考虑到nil检查,键入检查然后键入cast check,还有一个我想要添加的代码。 Swift背后的原因提供了很大的灵活性,但很难解决问题。假设我有一个字典,cityDetails,我正在尝试获取self.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

}

2 个解决方案

#1


5  

No need to unwrap the result from try. It is not an optional. You do need to cast the result from try to an NSDictionary. Use as? to downcast it.

无需从try中解包结果。它不是可选的。您需要将结果从try转换为NSDictionary。用于?贬低它。

Best practice: full access to returned error for good error handling

最佳实践:完全访问返回的错误以获得良好的错误处理

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)")
        }
    }
}

Quick and dirty: error handling is not for me!

快速而肮脏:错误处理不适合我!

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")
        }
    }
}

Bad Ass Mode: crashes are features

坏屁股模式:崩溃是功能

func parseData2(){
    var data:NSData?

    if let data2 = data  {

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

    }
}

Some extra info on multiple unwraps : Drop the code below in a playground.

多个unwraps的一些额外信息:在操场上删除下面的代码。

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()

#2


1  

You are looking for as?, which attempts to convert the thing on the left to the type on the right, and returns nil if the conversion is not possible:

您正在寻找?,它试图将左侧的东西转换为右侧的类型,如果转换不可能则返回nil:

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

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

You rarely need to use isKindOfClass in Swift. If you find yourself using it, ask why, and consider whether as or as? will work instead.

你很少需要在Swift中使用isKindOfClass。如果您发现自己使用它,请问为什么,并考虑是否为或?会改变。

#1


5  

No need to unwrap the result from try. It is not an optional. You do need to cast the result from try to an NSDictionary. Use as? to downcast it.

无需从try中解包结果。它不是可选的。您需要将结果从try转换为NSDictionary。用于?贬低它。

Best practice: full access to returned error for good error handling

最佳实践:完全访问返回的错误以获得良好的错误处理

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)")
        }
    }
}

Quick and dirty: error handling is not for me!

快速而肮脏:错误处理不适合我!

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")
        }
    }
}

Bad Ass Mode: crashes are features

坏屁股模式:崩溃是功能

func parseData2(){
    var data:NSData?

    if let data2 = data  {

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

    }
}

Some extra info on multiple unwraps : Drop the code below in a playground.

多个unwraps的一些额外信息:在操场上删除下面的代码。

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()

#2


1  

You are looking for as?, which attempts to convert the thing on the left to the type on the right, and returns nil if the conversion is not possible:

您正在寻找?,它试图将左侧的东西转换为右侧的类型,如果转换不可能则返回nil:

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

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

You rarely need to use isKindOfClass in Swift. If you find yourself using it, ask why, and consider whether as or as? will work instead.

你很少需要在Swift中使用isKindOfClass。如果您发现自己使用它,请问为什么,并考虑是否为或?会改变。