Swift中无法向Firebase实时数据库添加动态数据,旧数据被覆盖
问题原因与解决方案
核心问题1:setValue导致数据覆盖
setValue()方法会完全替换目标节点下的所有数据,而非追加新数据。你每次点击按钮时,都会把用户节点下的内容替换成仅包含当前nomeLocale的字典,自然会覆盖之前的数据。
核心问题2:键生成逻辑依赖本地数组计数,易出错
你用nomeLocale\(locali.count)作为键,但locali数组的计数依赖onAppear中的监听逻辑,这段逻辑存在明显问题:
.value事件会返回节点下的所有数据,但你的代码只尝试读取nomeLocale\(locali.count)对应的单个值,而非遍历所有子节点加载全部数据,导致locali数组无法正确同步数据库中的所有数据,计数始终不准确,会重复使用同一个键覆盖数据。
核心问题3:按钮内重复添加用户状态监听
每次点击按钮都调用Auth.auth().addStateDidChangeListener,会重复添加监听,既浪费资源,还可能导致多次执行写入逻辑。
修复步骤
1. 替换setValue为updateChildValues(或用自动生成键)
用updateChildValues()实现增量更新,只会更新指定键值对,不会覆盖其他已有数据;更推荐用childByAutoId()生成唯一键,彻底避免键重复问题:
Button(action: { guard let currentUser = Auth.auth().currentUser else { return } print(currentUser.email) print(locali) // 方案1:用Firebase自动生成唯一键(推荐) let newLocalRef = ref.child("locali").child(currentUser.uid).childByAutoId() newLocalRef.setValue(["nome": nomeLocale]) // 方案2:若坚持自定义键,用时间戳替代本地数组计数保证唯一 // let uniqueKey = "nomeLocale_\(Date().timeIntervalSince1970)" // ref.child("locali").child(currentUser.uid).updateChildValues([uniqueKey: nomeLocale]) }, label: { // ...按钮UI })
2. 修复数据读取逻辑,正确加载所有数据
在onAppear中遍历快照的所有子节点,把数据库中的全部数据加载到locali数组:
.onAppear { guard let userID = Auth.auth().currentUser?.uid else { return } ref.child("locali").child(userID).observe(.value, with: { snapshot in locali.removeAll() // 先清空旧数据,避免重复添加 for child in snapshot.children { guard let childSnapshot = child as? DataSnapshot, let nome = childSnapshot.value as? String else { continue } locali.append(nome) } }) }
3. 移除按钮内的重复状态监听
直接通过Auth.auth().currentUser获取当前用户,无需每次点击都添加监听。
内容的提问来源于stack exchange,提问作者alch_coder
相关产品推荐
相关产品推荐

