【问题标题】:Initializer for conditional binding must have Optional type, not 'AnyObject - Approach条件绑定的初始化程序必须具有 Optional 类型,而不是 'AnyObject - Approach
【发布时间】:2016-01-27 15:58:53
【问题描述】:

下面的代码会抛出一条消息,上面写着“条件绑定的初始化程序必须具有可选类型,而不是 '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 checktype 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

}

【问题讨论】:

  • 我不明白您在更新问题时要问什么?要么澄清它与第一部分的关系,要么为新部分提出一个新问题。目前您的标题涉及Optional Binding 问题,您的第一部分是关于do try catch,现在是关于down castingnil coalescing operator
  • 我对 nil check ,类型检查然后向下转换有点困惑,所有这些东西如何协同工作?简单的代码,但需要大量的理解。
  • is and asoptional bindingdo try catch。谷歌是一般语言问题的朋友。特别是当它涉及到最多的东西时
  • nil 检查是一个简单的 if else 取决于 nil/值。可选绑定为您提供来自可选输入的非可选结果。类型检查是一个简单的 if else 取决于类型。向下转换为您提供特定类型的可选结果。
  • 您有机会查看这些链接吗?

标签: ios swift let


【解决方案1】:

无需解开来自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")
        }
    }
}

Bad Ass Mode:崩溃是特征

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

【讨论】:

  • 好的,如果我不想使用 try catch 并检查两件事,对象不是 nil 和 isKindOfClass NSArray。如何以最简单的方式完成。
  • “崩溃是功能”你去吧
【解决方案2】:

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

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

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

您很少需要在 Swift 中使用 isKindOfClass。如果您发现自己在使用它,请询问原因,并考虑是否可以使用 asas?

【讨论】:

  • 如果 details 不为 null 并且恰好是 NSArray 怎么办?
  • 您的原始代码明确检查 NSDictionary,所以我假设您特别需要一个字典才能进行解析。如果您可以使用字典数组,那么您根本不需要类型检查;只需删除.AllowFragments,它将只允许字典和数组。请更详细地描述您要完成的工作。
  • [回复来自 R Menke 的已删除评论]:从原始代码中,看起来提问者正在尝试使用字典,在这种情况下,他们需要一个 NSDictionary 类型的变量,在条件展开中的as? 是正确的方法。如果他们的解析器代码应该在结果是NSDictionary 但实际上不需要任何特定于字典的调用(这不太可能但可能)时继续,那么is 确实是合适的。
  • @PaulCantrell 是的,我在操场上工作,可用代码有限,而且我太快了。我只是在回应他对我的回答的评论,他说他需要检查类型。没有预料到需要的沮丧。 is 仅用作检查,不能将其转换为类型。
猜你喜欢
  • 2021-04-26
  • 1970-01-01
  • 2015-10-19
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 2018-03-05
相关资源
最近更新 更多