Firebase实时数据库:如何获取已创建待办事项的节点Key?
问题
我正在开发一款待办事项(todolist)应用,包含两个界面:MainVC(列表页面)和SecondVC(带有两个输入框供用户填写笔记)。点击按钮时执行数据保存操作,代码如下:
private var databaseRef = Database.database().reference()
按钮点击事件代码:
let user = Auth.auth().currentUser self.databaseRef.child((user?.uid)!).child("tasklist").childByAutoId().setValue(["textPrimary":textPrimary, "textSecondary":textSecondary])
我使用childByAutoId()是因为一个用户可拥有多条笔记,数据库结构示例如下:
GcOialHBMfWxV9AgUJXR4zUsf603 = { // user.uid tasklist = { // child("tasklist") "-N9km0vd6W_gs3ljMRyw" = { // .childByAutoId() textPrimary = 123; //setValue(["textPrimary":textPrimary, textSecondary = Tasktask; // "textSecondary":textSecondary] }; "-N9km4EMruNUvSDsCCAY" = { // .childByAutoId() textPrimary = OtherTask; textSecondary = Taskkkkk; }; }; };
我需要获取已创建笔记的节点Key(例如:-N9km0vd6W_gs3ljMRyw),但当前在MainVC中加载数据的代码会通过childByAutoId()不断生成新的、数据库中不存在的Key:
// load data in first VC let user = Auth.auth().currentUser var ref = databaseRef.child("\(user!.uid)").child("tasklist").childByAutoId() print(ref) ref.observeSingleEvent(of: .value, with: { (snapshot) in print(snapshot.value) }) }
请问我的实现方式是否有误?若有误,正确的做法是什么?
解决方案
你的实现确实有误,问题出在MainVC加载数据时调用了childByAutoId()——这个方法的作用是生成一个全新的、唯一的节点ID,而非获取已存在的任务节点。每次调用它都会创建一个数据库中不存在的空节点,自然拿不到已有的任务数据。
正确加载数据并获取任务Key的代码
直接监听用户的tasklist节点,遍历该节点下的所有子节点(每个子节点对应一条任务),即可获取每条任务的Key和内容:
// MainVC中加载数据的正确代码 let user = Auth.auth().currentUser guard let uid = user?.uid else { return } // 直接指向用户的tasklist节点,不要调用childByAutoId() let taskListRef = databaseRef.child(uid).child("tasklist") taskListRef.observeSingleEvent(of: .value, with: { snapshot in // 遍历所有任务子节点 for childSnapshot in snapshot.children { guard let taskSnapshot = childSnapshot as? DataSnapshot else { continue } // 获取任务的唯一Key(即你需要的-N9km0vd6W_gs3ljMRyw这类值) let taskKey = taskSnapshot.key // 获取任务的文本内容 if let taskDict = taskSnapshot.value as? [String: Any] { let textPrimary = taskDict["textPrimary"] as? String ?? "" let textSecondary = taskDict["textSecondary"] as? String ?? "" print("任务Key: \(taskKey),主文本: \(textPrimary),副文本: \(textSecondary)") // 这里可以将任务数据和Key存入数组,用于更新UI列表 } } })
补充:保存任务时也可提前获取生成的Key
如果需要在SecondVC保存任务时就拿到生成的Key(比如用于后续修改/删除操作),可以先调用childByAutoId()获取节点引用,再提取Key后执行保存:
// SecondVC中保存任务并获取Key的代码 let user = Auth.auth().currentUser guard let uid = user?.uid else { return } let newTaskRef = databaseRef.child(uid).child("tasklist").childByAutoId() let taskKey = newTaskRef.key // 提前拿到生成的任务Key newTaskRef.setValue(["textPrimary": textPrimary, "textSecondary": textSecondary]) { error, ref in if let error = error { print("任务保存失败:\(error.localizedDescription)") } else { print("任务保存成功,Key:\(taskKey!)") } }
额外说明
如果需要实时同步任务数据(比如新增、修改、删除任务时自动更新MainVC的列表),可以将observeSingleEvent替换为observe,这样数据库数据变化时会自动触发回调,无需手动刷新。
内容的提问来源于stack exchange,提问作者user19478182
相关产品推荐
相关产品推荐

