如何解决Firebase数据读取时NSTaggedPointerString转NSDictionary崩溃问题
问题分析与解决方案
兄弟,你的崩溃原因其实很明确:写入Firebase的数据类型和读取时强制转换的类型完全不匹配!
问题根源
先看你的写入代码:
let childUpdates : [String : String] = ["\(uid!)/\(key)/": "true"] savedDB.updateChildValues(childUpdates)
这段代码在Firebase里生成的数据结构是:saved -> [用户uid] -> [帖子postid] = "true"
也就是说,每个帖子节点对应的是一个字符串值"true",而不是你读取时期望的字典类型。
但读取时你却强行把这个字符串转成字典:
let snapshotValue = snapshot.value as! Dictionary<String,String>
这就导致系统报错:无法把NSTaggedPointerString(Swift String在OC底层的对应类型)转换成NSDictionary,直接触发崩溃。
两种解决方案
你可以根据业务需求选择任意一种方案:
方案1:修改写入逻辑,存储字典类型(适合需要保存更多字段的场景)
如果你希望每个保存的帖子节点里包含postid等额外字段,把写入的值改成字典即可:
let savedDB = Database.database().reference().child("saved") // 先安全解包可选值,避免意外崩溃 guard let postid = detailpost?.postid, let uid = Auth.auth().currentUser?.uid else { return } let key = savedDB.child(postid).key // 将值替换为包含postid的字典 let childUpdates: [String: [String: String]] = ["\(uid)/\(key)/": ["postid": postid]] savedDB.updateChildValues(childUpdates)
此时Firebase的数据结构变成:saved -> [用户uid] -> [帖子postid] -> {postid: "xxx"}
你的原读取代码就能正常工作了(建议把as!改成as?做安全转换,进一步提升代码健壮性)。
方案2:修改读取逻辑,直接读取字符串值(适合仅标记是否保存的场景)
如果你的需求只是标记用户是否保存了某篇帖子,不需要额外字段,直接读取节点的字符串值,同时用snapshot.key获取postid:
if let uid = Auth.auth().currentUser?.uid{ let savedDB = Database.database().reference().child("saved").child(uid) savedDB.observe(.childAdded) { (snapshot) in // 安全转换为String,避免强制转换崩溃 if let isSaved = snapshot.value as? String, isSaved == "true" { // snapshot.key就是对应的帖子postid let savedpostid = snapshot.key // 继续你的业务逻辑 ...... } } }
额外小建议
以后处理Firebase数据时,尽量用**可选绑定(as?)**代替强制转换(as!),这样即使数据类型不符,也只会返回nil而不是直接崩溃,让你的代码更稳定。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

