Swift 不检索 Firebase 值(returns 值作为 NSNull)
Swift does not retrieve Firebase values (returns values as NSNull)
我正在尝试从我的 Firebase 实时数据库中提取值,但由于某种原因,这些值返回为 NSNull。我在第 13 行收到错误“无法将类型 'NSNull' 的值转换为 'NSNumber',直到我将 'let count = ...' 更改为 'if let'。我不确定为什么这些值不返回 null。
我已经尝试打印检索到的快照,并且如我所料,none 的值为空。我很难过。
这是打印检索到的快照时得到的日志:
[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)
}
}
这并不是一个完整的答案,但可能会为您提供正确的方向。代码中有一些令人困惑的地方,所以我会复习一下,然后可能会提供更好的方向...
您的函数传递了一个选定的日期
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 以进行排序可能是个好主意。
我正在尝试从我的 Firebase 实时数据库中提取值,但由于某种原因,这些值返回为 NSNull。我在第 13 行收到错误“无法将类型 'NSNull' 的值转换为 'NSNumber',直到我将 'let count = ...' 更改为 'if let'。我不确定为什么这些值不返回 null。
我已经尝试打印检索到的快照,并且如我所料,none 的值为空。我很难过。 这是打印检索到的快照时得到的日志:
[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)
}
}
这并不是一个完整的答案,但可能会为您提供正确的方向。代码中有一些令人困惑的地方,所以我会复习一下,然后可能会提供更好的方向...
您的函数传递了一个选定的日期
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 以进行排序可能是个好主意。