You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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个参数仍无法解决,相关代码见原文。

错误原因

  1. 闭包参数不匹配:当前Firebase SDK版本中,observeSingleEvent的闭包要求接收两个参数(DataSnapshot和Error?),原代码仅传入一个参数,导致类型推断异常。
  2. 类型转换错误:结构体Koordinatlarlarimsi的属性为Float类型,但从Firebase取出的是Int类型,直接赋值会触发类型不兼容错误。
  3. 节点遍历不安全:未对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:27:08