Firebase回调报错:Void需2个参数&NSObject无children成员
Firebase数据读取与结构体赋值问题解决方案
问题说明
我尝试获取Firebase中Harita/Pancarlar路径下每个子节点的数据,通过自定义结构体Koordinatlarlarimsi将数据赋值给变量KoordinatAsil,但执行以下代码时出错:
self.KoordinatAsil = Koordinatlarlarimsi(koordinatx: koordinatX, koordinaty: koordinatY, width: Width, height: Height, differenceBetween: 0)
报错信息(已翻译):
上下文闭包类型 '(DataSnapshot, String?) -> Void' 需要2个参数,且类型为 'NSObject' 的值没有成员 'children'。
尝试传入2个参数仍无法解决,相关代码见原文。
错误原因
- 闭包参数不匹配:当前Firebase SDK版本中,
observeSingleEvent的闭包要求接收两个参数(DataSnapshot和Error?),原代码仅传入一个参数,导致类型推断异常。 - 类型转换错误:结构体
Koordinatlarlarimsi的属性为Float类型,但从Firebase取出的是Int类型,直接赋值会触发类型不兼容错误。 - 节点遍历不安全:未对
snapshot的有效性做校验,直接访问children可能导致类型推断错误。
修正后的完整代码
struct Koordinatlarlarimsi { let koordinatx: Float let koordinaty: Float let width: Float let height: Float let differenceBetween: Float } class HaritaFirebaseVC: UIViewController { var database: DatabaseReference! var Koordinatciklar: [Koordinatlarlarimsi] = [] var KoordinatAsil: Koordinatlarlarimsi? override func viewDidLoad() { super.viewDidLoad() database = Database.database().reference() database.child("Harita").child("Pancarlar").observeSingleEvent(of: .value) { snapshot, error in // 处理Firebase读取错误 guard error == nil else { print("数据读取失败:\(error!.localizedDescription)") return } // 校验快照是否存在,且子节点可转换为DataSnapshot数组 guard snapshot.exists(), let childSnapshots = snapshot.children.allObjects as? [DataSnapshot] else { print("无有效子节点数据") return } for child in childSnapshots { // 转换子节点值为字典类型 guard let dataDict = child.value as? [String: Any] else { print("子节点数据格式错误") continue } // 安全取出字段并转换类型 guard let koordinatX = dataDict["koordinatX"] as? Int, let koordinatY = dataDict["koordinatY"] as? Int, let height = dataDict["Height"] as? Int, let width = dataDict["width"] as? Int else { print("字段缺失或类型不匹配") continue } // 创建结构体实例,注意将Int转为Float let koordinat = Koordinatlarlarimsi( koordinatx: Float(koordinatX), koordinaty: Float(koordinatY), width: Float(width), height: Float(height), differenceBetween: 0 ) // 保存到数组(保留所有子节点数据) self.Koordinatciklar.append(koordinat) // 若仅需最后一个子节点数据,赋值给KoordinatAsil self.KoordinatAsil = koordinat } // 若需更新UI,切换到主线程 DispatchQueue.main.async { // 这里执行UI刷新操作,比如表格重载等 } } } }
核心修正点
- 给闭包添加
error参数,处理Firebase读取可能出现的异常。 - 对
snapshot的存在性和子节点类型做安全校验,避免类型推断错误。 - 将从Firebase获取的
Int类型数据显式转换为Float,匹配结构体属性类型。 - 使用
guard语句替代强制解包,避免崩溃。 - 若需要保留所有子节点数据,将实例添加到
Koordinatciklar数组;若仅需单个节点数据,最后一次循环的赋值会保留最后一个子节点的数据。
内容的提问来源于stack exchange,提问作者Erkan Coşar
相关产品推荐
相关产品推荐

