Swift & Firebase问题:修改数据后Observer返回nil
解决Firebase ChildAdded观察者修改数据后返回nil的问题
我来帮你排查下这个问题,这种情况在Firebase实时数据库的观察者使用中挺常见的,咱们一步步来分析可能的原因和解决办法:
1. 先确认数据是否真的从Firebase返回
首先你可以在观察者的闭包里加几行打印代码,看看实际收到的snapshot是什么样的:
func download() { byer.removeAll() self.Handle = self.ref?.child("Byer").observe(.childAdded, with: { (snapshot) in // 新增打印,排查数据情况 print("当前快照内容:\(snapshot)") print("快照对应的值:\(snapshot.value ?? "没有获取到值,为nil")") if let dictionary = snapshot.value as? [String: AnyObject] { let by = By() by.Latitude = dictionary["Latitude"]?.doubleValue by.Longitude = dictionary["Longitude"]?.doubleValue // ... 其他字段赋值 self.byer.append(by) // 记得刷新UI } }) }
运行修改数据的操作后,看控制台的输出:
- 如果快照本身是nil,那大概率是权限问题或者ref指向错误
- 如果快照有内容但转成
[String: AnyObject]失败,那就是数据结构或类型和你预期的不匹配(比如字段名写错、类型从Double改成了String)
2. 注意childAdded的触发逻辑
childAdded观察者只会在新增节点时触发,如果你是修改已存在的节点,这个观察者是不会响应的!这是很多开发者容易踩的坑。
如果需要处理数据修改的情况,你需要额外监听childChanged事件,同时给你的By对象加上一个和Firebase节点key对应的id属性,这样才能找到要更新的数组元素:
// 在download函数里同时添加childChanged监听 self.ref?.child("Byer").observe(.childChanged, with: { (snapshot) in guard let dictionary = snapshot.value as? [String: AnyObject], let byId = snapshot.key else { print("解析修改后的数据失败") return } // 找到数组中对应的By对象 if let index = self.byer.firstIndex(where: { $0.id == byId }) { let updatedBy = By() updatedBy.id = byId updatedBy.Latitude = dictionary["Latitude"]?.doubleValue updatedBy.Longitude = dictionary["Longitude"]?.doubleValue // ... 其他字段赋值 self.byer[index] = updatedBy // 刷新UI,比如tableView.reloadData() } })
3. 检查观察者是否被意外移除或ref为nil
- 确认你没有在VC的生命周期方法(比如
viewWillDisappear)里提前移除了这个观察者,或者调用了removeAllObservers() - 检查
self.ref的初始化时机,尽量不要在VC的init方法里初始化Firebase引用,建议放在viewDidLoad里,因为初始化阶段Firebase可能还没完成配置,导致ref为nil
4. 排查Firebase数据库权限
修改数据后,当前用户是否还拥有读取Byer节点的权限?你可以去Firebase控制台的「实时数据库」→「规则」里检查,确保规则允许当前用户读取该节点,比如:
{ "rules": { "Byer": { ".read": "auth != null", // 确保已登录用户可以读取 ".write": "auth != null" } } }
如果权限不匹配,Firebase会返回nil,同时控制台会输出权限错误的日志。
你可以按照上面的步骤一步步排查,应该能找到问题所在!
内容的提问来源于stack exchange,提问作者Lasse Bickmann
相关产品推荐
相关产品推荐

