【问题标题】:Swift does not retrieve Firebase values (returns values as NSNull)Swift 不检索 Firebase 值(以 NSNull 形式返回值)
【发布时间】:2019-04-14 05:19:40
【问题描述】:

我正在尝试从我的 Firebase 实时数据库中提取值,但无论出于何种原因,这些值都以 NSNull 的形式返回。在我将 'let count = ...' 更改为 'if let' 之前,我在第 13 行收到错误消息“无法将 'NSNull' 类型的值转换为 'NSNumber'。我不确定为什么这些值不返回 null。

我已经尝试打印检索到的快照,并且正如我所料,没有一个值是空的。我难住了。 这是我打印检索到的快照时得到的日志:

[Snap (A12-1A) 0, Snap (B1-2A) 0, Snap (C2-3A) 0, Snap (D3-4A) 0, Snap (E4-5A) 0, Snap (F5-6A) 0, Snap (G6-7A) 0, Snap (H7-8A) 0, Snap (I8-9A) 0, Snap (J9-10A) 5, Snap (K10-11A) 0, Snap (L11-12P) 0, Snap (M12-1P) 0, Snap (N1-2P) 0, Snap (O2-3P) 0, Snap (P3-4P) 0, Snap (Q4-5P) 0, Snap (R5-6P) 0, Snap (S6-7P) 0, Snap (T7-8P) 0, Snap (U8-9P) 0, Snap (V9-10P) 0, Snap (W10-11P) 0, Snap (X11-12A) 0]

此快照中的所有数据都是我的 Firebase 数据库中的数据,所以我不确定为什么会出现此错误。

我的 Firebase 设置:日历注册 --- 04132019 --- (A12-1A: 0, B1-2A: 0, ..., X11-12P: 0)

func getCalendarSignupsOnDate(selectedDate: String, handler: @escaping (_ dateSignups: [Calendar]) -> ()) {
        var calendarArray = [Calendar]()

        REF_CALENDAR_SIGNUPS.observeSingleEvent(of: .value) { (snapshot) in
            guard let snapshot = snapshot.children.allObjects as? [DataSnapshot] else { return }

            var doesContainDate = false
            for date in snapshot {
                if date.key == selectedDate {
                    doesContainDate = true

                    self.REF_CALENDAR_SIGNUPS.child(date.key).observeSingleEvent(of: .value, with: { (dateSnapshot) in
                        guard let dateSnapshot = dateSnapshot.children.allObjects as? [DataSnapshot] else { return }

                        for timeSlots in dateSnapshot {
                            let time = timeSlots.key
                            if let count = timeSlots.childSnapshot(forPath: "J9-10A").value as? Int {
                                let calendarData = Calendar(time: time, signupCount: count)
                                calendarArray.append(calendarData)
                                handler(calendarArray)
                            } else {
                                let count = 0
                                let calendarData = Calendar(time: time, signupCount: count)
                                calendarArray.append(calendarData)
                                handler(calendarArray)
                            }
                        }
                    })
                }
            }
            for item in calendarArray {
                print(item.time + " " + String(item.signupCount))
            }
            if doesContainDate == false {
                let dateSignUpData = [
                    "A12-1A": 0,
                    "B1-2A": 0,
                    "C2-3A": 0,
                    "D3-4A": 0,
                    "E4-5A": 0,
                    "F5-6A": 0,
                    "G6-7A": 0,
                    "H7-8A": 0,
                    "I8-9A": 0,
                    "J9-10A": 0,
                    "K10-11A": 0,
                    "L11-12P": 0,
                    "M12-1P": 0,
                    "N1-2P": 0,
                    "O2-3P": 0,
                    "P3-4P": 0,
                    "Q4-5P": 0,
                    "R5-6P": 0,
                    "S6-7P": 0,
                    "T7-8P": 0,
                    "U8-9P": 0,
                    "V9-10P": 0,
                    "W10-11P": 0,
                    "X11-12A": 0
                    ]
                    as [String : Int]

                self.REF_CALENDAR_SIGNUPS.child(selectedDate).updateChildValues(dateSignUpData)

                for timeSlots in dateSignUpData {
                    let time = timeSlots.key
                    let count = timeSlots.value
                    let calendarData = Calendar(time: time, signupCount: count)
                    calendarArray.append(calendarData)
                }
            }

            handler(calendarArray)
        }
    }

【问题讨论】:

  • 欢迎来到 SO。关于提问的几件事,请使代码尽可能简短,并删除不适用的内容。见How to create a Minimal, Complete, and Verifiable example。其次,最好从 Firebase 控制台发布您的 Firebase 结构的 sn-p。要获取您的 Firebase 结构,请使用 Firebase 控制台->导出 JSON 并复制并粘贴一个 sn-p
  • 有点不清楚您要实现的目标,但更重要的是,代码会反复从 Firebase 中读取您已经阅读过的相同数据 - 不知道为什么。这行REF_CALENDAR_SIGNUPS.observeSingleEvent 读取该节点内的ALL 数据。然后再次读取完全相同的数据self.REF_CALENDAR_SIGNUPS.child(date.key).observeSingleEvent。由于数据已被读取,请在内存中使用它 - 再次点击 FB 毫无意义。保持一致也很重要。如果您在一个地方使用 self.REF_CALENDAR_SIGNUPS(这是正确的使用方式),那么每个人都应该使用它。

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


【解决方案1】:

这并不是一个完整的答案,但可能会为您提供正确的方向。代码中有一些令人困惑的地方,所以我会回顾一下,然后可能会提供更好的方向......

你的函数被传递了一个选定的日期

func getCalendarSignupsOnDate(selectedDate: String

这意味着您知道要读取的日期节点。但是,代码正在读取所有日期并对其进行迭代以尝试找到该日期

 for date in snapshot {
   if date.key == selectedDate {

直接读取该节点,然后使用其中的子节点可能会少很多代码。

此外,在代码的更下方,您正在遍历 A12-1A、B1-2A 的子节点,寻找特定节点

if let count = timeSlots.childSnapshot(forPath: "J9-10A").value as? Int

这根本不起作用,因为 timeSlots A12-1A 等的值都是 0,而不是子快照。代码继续显示您想要读取该特定子节点的值,然后将其余部分设置为 0,这些将添加到您的日历数组中。

let count = 0
let calendarData = Calendar(time: time, signupCount: count)

但是再往下看,如果你没有找到那个时间段,所有的子节点都设置为 0。

if doesContainDate == false {
    let dateSignUpData = [
       "A12-1A": 0,
       "B1-2A": 0,

所以...我想我明白了你想要做的事情的要点。下面是一些可能让你朝着正确方向前进的代码。这应该替换您问题中的所有代码。

func getCalendarSignupsOnDate(selectedDate: String) {
    var dateSignUpData = [
        "A12-1A": 0,
        "B1-2A": 0,
        "C2-3A": 0,
        "J9-10A": 0
    ]
    let slotYourLookingFor = "J9-10A"
    let dateRef = self.REF_CALENDAR_SIGNUPS.child(selectedDate).child(slotYourLookingFor)
    dateRef.observeSingleEvent(of: .value, with: { snapshot in
        if snapshot.exists() {
            let count = snapshot.value as? Int ?? 0
            dateSignUpData[slotYourLookingFor] = count //update this array element with the new count from Firebaes
        } else { //didn't find the child node at all, will create the date node and add child nodes with val = 0
            self.REF_CALENDAR_SIGNUPS.child(selectedDate).updateChildValues(dateSignUpData)
        }
        //do something with the dateSignUpData array
    })
}

解释:

输入您感兴趣的日期。代码将读取具有“J9-10A”子节点的那个节点,即您要查找的那个。

如果存在,它将读取该数据并使用来自该子节点的计数更新 dateSignUpData 数组。然后您可以进一步处理更新后的数组。

如果“J9-10A”节点不存在,将创建一个传入日期的节点,然后将所有子节点槽设置为0。然后您可以进一步处理数组。

最后一件事。将日期存储为 yyyymmdd 可能是个好主意。

【讨论】:

    猜你喜欢
    • 2017-07-09
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 2017-11-29
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多