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

Initializer for conditional binding must have Optional type, not 'AnyObject - Approach

以下代码会抛出一条消息 "Initializer for conditional binding must have Optional type, not '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,我还想添加一个代码检查。 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

}

无需解包 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?,它试图将左边的东西转换为右边的类型,如果无法转换,则 returns nil:

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

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

您很少需要在 Swift 中使用 isKindOfClass。如果您发现自己在使用它,问问为什么,并考虑 asas? 是否会起作用。