【问题标题】:Firebase Retrieve Data - Could not cast valueFirebase 检索数据 - 无法转换值
【发布时间】:2017-02-17 11:38:51
【问题描述】:

首先,我检查了这些对我没有帮助的答案: Swift JSON error, Could not cast value of type '__NSArrayM' (0x507b58) to 'NSDictionary' (0x507d74)

Get data from Firebase

从 Firebase (3.x) 检索数据时,出现以下错误:

Could not cast value of type '__NSArrayM' (0x10ca9fc30) to 'NSDictionary' (0x10caa0108).

使用此代码和树:

树:

检索函数:

func retrievePlanes() {

    print("Retrieve Planes")

    ref = FIRDatabase.database().reference(withPath: "results")

    ref.observe(.value, with: { snapshot in

        var newItems: [Planes] = []

        for item in snapshot.children {
            let planesItem = Planes(snapshot: item as! FIRDataSnapshot)
            newItems.append(planesItem)
        }

        self.planes = newItems
        self.tableView.reloadData()

    })

}

Planes.swift - 管理数据

import Foundation
import Firebase
import FirebaseDatabase

struct Planes {

    let key: String!
    let name: String!
    let code:String!
    let flightRange: Int?
    let typicalSeats: Int?
    let maxSeats: Int?
    let wingSpan: String!
    let takeoffLength: Int?
    let rateClimb: Int?
    let maxCruiseAltitude: Int?
    let cruiseSpeed: String!
    let landingLength: Int?
    let engines: String!
    let votes: Int?
    let data: String!
    let imagePlane:String!
    let imageTakenFrom: String!
    let ref: FIRDatabaseReference?

    init(name: String, code: String, flightRange: Int, typicalSeats: Int, maxSeats: Int, wingSpan: String, takeoffLength: Int, rateClimb: Int, maxCruiseAltitude: Int, cruiseSpeed: String, landingLength: Int, engines: String, votes: Int, data: String, imagePlane: String, imageTakenFrom: String, key: String = "") {

        self.key = key
        self.name = name
        self.code = code
        self.flightRange = flightRange
        self.typicalSeats = typicalSeats
        self.maxSeats = maxSeats
        self.wingSpan = wingSpan
        self.takeoffLength = takeoffLength
        self.rateClimb = rateClimb
        self.maxCruiseAltitude = maxCruiseAltitude
        self.cruiseSpeed = cruiseSpeed
        self.landingLength = landingLength
        self.engines = engines
        self.votes = votes
        self.data = data
        self.imagePlane = imagePlane
        self.imageTakenFrom = imageTakenFrom
        self.ref = nil

    }

    init(snapshot: FIRDataSnapshot) {

        ref = snapshot.ref
        key = snapshot.key
        let snapshotValue = snapshot.value as! [String:AnyObject]
        name = snapshotValue["name"] as! String
        code = snapshotValue["code"] as! String
        flightRange = snapshotValue["intFlightRange"] as? Int
        typicalSeats = snapshotValue["intTypicalSeats"] as? Int
        maxSeats = snapshotValue["intMaxSeats"] as? Int
        wingSpan = snapshotValue["wingSpan"] as! String
        takeoffLength = snapshotValue["intTakeoffLength"] as? Int
        rateClimb = snapshotValue["intRateClimb"] as? Int
        maxCruiseAltitude = snapshotValue["intMaxCruiseAltitude"] as? Int
        cruiseSpeed = snapshotValue["cruiseSpeed"] as! String
        landingLength = snapshotValue["intLandingLength"] as? Int
        engines = snapshotValue["engines"] as! String
        votes = snapshotValue["votes"] as? Int
        data = snapshotValue["data"] as! String
        imagePlane = snapshotValue["planeImage"] as! String
        imageTakenFrom = snapshotValue["imageTakenFrom"] as! String
    }

上线:let snapshotValue = snapshot.value as! [String:AnyObject]

我想这是由于下面的Int 导致无法在[String:AnyObject] 下检索快照值。 (在另一种情况下,当我只有 String 时它正在工作)。

我也知道 Firebase 将 JSON 树“转换”为这些对象[link]

  • NSString
  • NSNumber
  • NSArray
  • NSDictionnary

但我不知道要在 snapshot.value 行中更改什么才能使其正常工作。

感谢您的帮助。

编辑:我刚刚发送了故障排除请求。将发布更新。 编辑 2:请参阅 Jay 的回答。就我而言,树是错误的。

【问题讨论】:

  • 将您的 JSON 树结构和代码提供给您检索它的位置。
  • @Dravidian 给你!
  • init(snapshot: FIRDataSnapshot) 构造函数以前工作过吗?
  • @EmilDavid 它目前甚至正在另一个没有“Int”的数据库上工作
  • 你试过直接追加到数组吗? self.planes.append(planesItem) 在循环中?在您的检索功能中。

标签: ios json swift firebase firebase-realtime-database


【解决方案1】:

我把你的代码缩小了一点进行测试,它正在工作。 (注意 OS X 和 Swift 3 上的 Firebase 2.x,但代码相似)

Firebase 结构:

  "what-am" : {
    "results" : [ {
      "code" : "738/B738",
      "data" : "Boeing",
      "engines" : "Rolls"
    }, {
      "code" : "727/B727",
      "data" : "Boeing",
      "engines" : "Pratt"
    } ]
  }

这是平面结构

struct Planes {

    var code:String!
    var data: String!
    var engines: String!

    init(code: String, data: String, engines: String ) {

        self.code = code
        self.data = data
        self.engines = engines
    }

    init(snapshot: FDataSnapshot) {

        let snapshotValue = snapshot.value as! [String:AnyObject]

        code = snapshotValue["code"] as! String
        data = snapshotValue["data"] as! String
        engines = snapshotValue["engines"] as! String
    }
}

然后代码在两个平面中读取,填充和数组,然后打印数组。

let ref = self.myRootRef.child(byAppendingPath: "what-am/results")!

ref.observe(.value, with: { snapshot in

        if ( snapshot!.value is NSNull ) {
            print("not found")
        } else {

            var newItems: [Planes] = []

            for item in (snapshot?.children)! {
                let planesItem = Planes(snapshot: item as! FDataSnapshot)
                newItems.append(planesItem)
            }

            self.planes = newItems
            print(self.planes)

        }
})

最后是输出

[Swift_Firebase_Test.Planes(code: 738/B738, data: Boeing, engines: Rolls),
 Swift_Firebase_Test.Planes(code: 727/B727, data: Boeing, engines: Pratt)]

当我从 Planes 结构中删除时,键和名称为零。

你问的那行

let snapshotValue = snapshot.value as! [String:AnyObject]

有效,因为快照包含一系列键:值对,因此 String:AnyObject 有效。

由于 Swift 3,这一行发生了变化

for item in (snapshot?.children)!

但除此之外,代码可以工作。

试试这个以确保您正在读取正确的节点。这将读取上述结构并打印出每个引擎类型。 (经过测试和工作)

 let ref = self.myRootRef.child(byAppendingPath: "what-am/results")!
 ref.observe(.value, with: { snapshot in
      if ( snapshot!.value is NSNull ) {
           print("not found")
      } else {
           for child in (snapshot?.children)! {
                let snap = child as! FDataSnapshot
                let dict = snap.value as! [String: String]
                let engines = dict["engines"]
                print(engines!)
           }    
      }
 })

【讨论】:

  • .child(byAppendingPath: ) 已弃用。
  • 所以我应该将 snapshotValue 行更改为 (snapshot?.children) 中的 for 项?
  • @EmilDavid 是的,我意识到,根据我在顶部的注释(Firebase 2.x),这已经贬值了,但是,Firebase 表示他们“仍然支持”2.x“未来一段时间”以及何时你有一个 macOS 上的代码库,你不能使用 3。
  • @antoinebelldev 我必须这样做才能在 Swift 3 中进行迭代更改。在您的情况下,在 snapshot.children 中使用 for item 是 Swift 2 中的正确顺序。我在我的末尾添加了一个建议回答。
  • 不工作。对于“让引擎...”行,我有错误:Any 类型没有下标成员
【解决方案2】:

我认为您在 firebase 数据的结果键值中有一个额外的数组。

  • 您应该尝试删除该数组或

  • 您可以从数组的第一个索引中检索字典,例如;

    // .. your code
    let snapshotValue = (snapshot.value as! [AnyObject])[0] as! [String:AnyObject];
    // .. your code
    

【讨论】:

  • 不,不工作。错误:无法将“__NSDictionnaryM”类型的值转换为“NSArray”
【解决方案3】:

在你的结构类中确保这些事情:-

  • 避免将变量声明为 :Int?,因为这实际上是 nil,请将它们更改为 :Int!

  • 您在 Firebase 中的密钥是一个 Int,并且您将 struct 中的密钥声明为 let key: String!,将其更改为 let key: Int!

  • 首选您的快照字典声明为 let snapshotValue = snapshot.value as! [AnyHashable:Any](根据 swift 3)

然后你的初始化函数:-

换行就行了

let snapshotValue = snapshot.value as! [String:AnyObject]

let snapshotValue = (snapshot.value as! NSArray)[0] as! [String:AnyObject]

【讨论】:

  • 所以我更改了 Int 和快照声明,但我仍然有同样的错误。
  • 错误发生在这一行,所以我不能有 print()
  • 对于“让 snapshotValue = snapshot.value ...”行我有一个错误 =>“类型 '[String:AnyObject]' 的值没有成员 'value'。
  • 还是不行。感谢您之前的所有回答:)
  • 好的,我试试。 Key 也是 Firebase 中的字符串,将其更改为 Int 告诉我。
【解决方案4】:

将 FIRDataSnapshot 更新为 DataSnapshot Swift 4

【讨论】:

    【解决方案5】:

    以下是 Swift 4 的示例。您需要将 FIRDataSnapshot 更改为 DataSnapshot

        func fetchChats(chatId: String) {
        ref.child("chats").child("SomeChildId").observe(.value) { (snapshot) in
            for child in snapshot.children {
                let data = child as! DataSnapshot //<--- Update this line
                let dict = data.value as! [String: AnyObject]
                let message = dict["message"]
                print(message!)
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-07
      • 2018-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-24
      • 2018-04-06
      • 1970-01-01
      相关资源
      最近更新 更多