【问题标题】:Cannot call value of non-function type 'Any?!' :- Firebase,Swift3无法调用非函数类型“任何?!”的值:- Firebase,Swift3
【发布时间】:2016-09-17 20:22:59
【问题描述】:

这是我迁移到 Swift 3 之前的代码:

ref.observeEventType(.ChildAdded, withBlock: { snapshot in
            let currentData = snapshot.value!.objectForKey("Dogs")
            if currentData != nil {
            let mylat = (currentData!["latitude"])! as! [String]
            let mylat2 = Double((mylat[0]))
            let mylon = (currentData!["longitude"])! as! [String]
            let mylon2 = Double((mylon[0]))
            let userid = (currentData!["User"])! as! [String]
            let userid2 = userid[0]
            let otherloc = CLLocation(latitude: mylat2!, longitude: mylon2!)
            self.distanceBetweenTwoLocations(self.currentLocation, destination: otherloc, userid: userid2)
            }
        })

这是我迁移到 Swift 3 之后的代码:

ref.observe(.childAdded, with: { snapshot in
            let currentData = (snapshot.value! as AnyObject).object("Dogs")
            if currentData != nil {
                let mylat = (currentData!["latitude"])! as! [String]
                let mylat2 = Double((mylat[0]))
                let mylon = (currentData!["longitude"])! as! [String]
                let mylon2 = Double((mylon[0]))
                let userid = (currentData!["User"])! as! [String]
                let userid2 = userid[0]
                let otherloc = CLLocation(latitude: mylat2!, longitude: mylon2!)
                self.distanceBetweenTwoLocations(self.currentLocation, destination: otherloc, userid: userid2)
            }
        })

然后我在第二行得到一个错误:

不能调用非函数类型'Any?!'的值

我唯一尝试的是将第二行更改为以下代码:

snapshot.value as! [String:AnyObject]

但这是不对的,其中没有包含“Dogs”,它警告我distanceBetweenTwoLocations 代码从未使用过。

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    看到问题是,当您实例化和初始化变量时,您告诉它它将接收到的值将是 value 用于此快照中名为 Dogs 的对象其类型为AnyObject

    但是 snapshot.value 是字典类型,即[String:AnyObject],NSDictionary..

    您检索的Dogs 节点的类型是字典或数组。

    基本上,您应该避免将值存储在 AnyObject 类型的变量中

    试试这个:-

          FIRDatabase.database().reference().child("Posts").child("post1").observe(.childAdded, with: { snapshot in
            if let currentData = (snapshot.value! as! NSDictionary).object(forKey: "Dogs") as? [String:AnyObject]{
    
                let mylat = (currentData["latitude"])! as! [String]
                let mylat2 = Double((mylat[0]))
                let mylon = (currentData["longitude"])! as! [String]
                let mylon2 = Double((mylon[0]))
                let userid = (currentData["User"])! as! [String]
                let userid2 = userid[0]
                let otherloc = CLLocation(latitude: mylat2!, longitude: mylon2!)
                self.distanceBetweenTwoLocations(self.currentLocation, destination: otherloc, userid: userid2)
            }
        })
    

    PS:-看到您的 JSON 结构,您可能想将其转换为字典而不是数组

    【讨论】:

    • 我在 if 行中收到警告:Comparing non-optional value of type '[String : AnyObject]' to nil always returns true 以及我在问题中写的distanceBetweenTwoLocations 中的警告。
    • 我已经更新了我的答案。至于 distanceBetweenTwoLocations 我不能说话,因为我看不到你的代码中写了什么..
    • 现在它通过 currentData (在我删除 child("Posts").child("post1") 之后。但由于某种原因仍然在 distanceBetweenTwoLocations 中收到警告,在迁移到 Swift 3 之前我没有这个问题
    • distanceBetweenTwoLocations 是什么,你在哪里声明的。如果没有更多信息,无法为您提供帮助..
    • 是的,它帮助了我,而且是正确的!非常感谢你!显然,由于 Firebase 身份验证连接,distanceBetweenTwoLocations 不起作用。如果您想提供帮助,我在这里提出了新问题:):stackoverflow.com/questions/39556586/…
    【解决方案2】:

    在 Swift 3 中,AnyObject 已更改为 Any,这实际上可以是任何东西。 尤其是在使用键和索引下标时,现在需要告诉编译器实际类型。

    解决方案是将 snapshot.value 转换为 Swift 字典类型 [String:Any] 。可选绑定安全地展开值

    if let snapshotValue = snapshot.value as? [String:Any], 
       let currentData = snapshotValue["Dogs"] as? [String:Any] {
    
         let mylat = currentData["latitude"] as! [String]
         ...
    

    您使用的感叹号过多。 latitude"] 之后的标记在 as! 之前不需要并且始终使用 if let 而不是检查 nil

    【讨论】:

    • 到目前为止还不错,但在 distanceBetweenTwoLocations 行代码中我收到警告:Result of call to 'distanceBetweenTwoLocations(_:destination:userid:)' is unused。正如它警告我的那样 - 由于某种原因,它从未使用过(它在更改为 Swift 3 之前使用过)。
    • 在不使用结果的情况下调用方法进行计算是荒谬的。
    • 您在 Swift 3 之前的代码也不使用结果。在 Swift 3 中,您会收到更多关于未使用结果的警告,您可以将 @discardableResult 放在函数前面,或者如果根本不使用结果,则删除结果类型。
    • 不可能!它工作得很好!它显示了该位置之间的所有用户,更改为 swift 3 后没有任何反应。 @discardableResult 是什么?
    • 获得currentData 的可选绑定是否通过了? @discardableResult 抑制 unused result 警告。
    【解决方案3】:

    我还有一个代码片段,它允许您访问子节点的值。希望对您有所帮助:

    if let snapDict = snapShot.value as? [String:AnyObject] {
    
                for child in snapDict{
    
                    if let name = child.value as? [String:AnyObject]{
    
                        var _name = name["locationName"]
                        print(_name)
                    }
    
                }
    
            }
    

    最好的问候, 纳扎尔·梅德罗斯

    【讨论】:

      猜你喜欢
      • 2016-09-16
      • 2016-10-04
      • 2017-08-16
      • 2020-02-01
      • 2021-01-15
      • 2021-03-30
      • 2016-03-10
      • 2016-09-26
      • 2017-06-27
      相关资源
      最近更新 更多