iOS读取Firebase数据库单个子节点值遇NSUnknownKeyException报错求解
解决iOS Firebase读取
BitcoinAddress字段时的SIGABRT错误 嘿,我一眼就看出问题出在哪了!你遇到的SIGABRT错误,根源是用错了Firebase数据读取的方式,咱们一步步来解决:
错误原因分析
你写的self.ref?.child("Users").child((Auth.auth().currentUser?.uid)!).value(forKey: "BitcoinAddress")用了**Key-Value Coding(KVC)**的value(forKey:)方法,但FIRDatabaseReference类根本不支持这种方式获取数据——它不是遵循KVC的模型类,自然会抛出NSUnknownKeyException,提示“这个类不支持key BitcoinAddress的键值编码”。
另外,Firebase数据库的读取是异步操作,你不能像同步赋值那样直接拿到数据,必须用它的回调监听机制来获取结果,同时这也能满足你“动态读取更新后的值”的需求。
正确实现代码
下面是修正后的代码,既能正确读取BitcoinAddress,又能实时监听字段的更新:
import FirebaseAuth import FirebaseDatabase class YourViewController: UIViewController { var bitcoinAddressText = "" // 假设你已经在Storyboard/XIB中关联了这个标签的IBOutlet @IBOutlet weak var bitcoinAddressLabel: UILabel! var ref: DatabaseReference! // 保存监听的引用,方便后续移除监听 var userDataListener: DatabaseHandle? override func viewDidLoad() { super.viewDidLoad() ref = Database.database().reference() // 先判断用户是否已登录,避免空指针崩溃 guard let currentUserUID = Auth.auth().currentUser?.uid else { DispatchQueue.main.async { self.bitcoinAddressLabel.text = "请先登录" } return } // 指向当前用户的节点 let currentUserRef = ref.child("Users").child(currentUserUID) // 监听节点数据变化,实现动态读取 userDataListener = currentUserRef.observe(.value, with: { [weak self] snapshot in guard let self = self else { return } // 从快照中解析数据 if let userDict = snapshot.value as? [String: Any], let bitcoinAddr = userDict["BitcoinAddress"] as? String { self.bitcoinAddressText = bitcoinAddr // 更新UI必须在主线程(Firebase回调默认在后台线程) DispatchQueue.main.async { self.bitcoinAddressLabel.text = bitcoinAddr } } else { // 处理数据不存在或解析失败的情况 DispatchQueue.main.async { self.bitcoinAddressLabel.text = "未设置比特币地址" } } }) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 页面销毁时移除监听,避免内存泄漏 if let listener = userDataListener, let uid = Auth.auth().currentUser?.uid { ref.child("Users").child(uid).removeObserver(withHandle: listener) } } }
关键注意点
- 异步回调与主线程更新:Firebase的回调会在后台线程执行,所以更新UI时一定要用
DispatchQueue.main.async切换到主线程,否则会触发UI线程错误。 - 实时监听:使用
observe(.value)会在节点数据发生任何变化时触发回调,完美满足你“用户更新字段后动态读取”的需求。 - 权限设置:确保你的Firebase数据库规则允许当前用户读取自己的节点,否则会出现权限错误。示例规则如下:
{ "rules": { "Users": { "$uid": { ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" } } } }
- 移除监听:在页面销毁时记得移除监听,避免内存泄漏和不必要的资源消耗。
内容的提问来源于stack exchange,提问作者Adam Zyluk
相关产品推荐
相关产品推荐

