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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 02:45:36