Swift开发中如何在Firebase中正确存储uid与FCM令牌
问题原因
当前代码存在三个核心问题,导致UID无法正常写入、存储结构不符合预期:
- 引用初始化顺序错误:
ref的赋值操作放在了写入数据的逻辑之后,且生成存储节点key的逻辑有误,self.ref.childByAutoId().child("Uid").key拿到的不是token节点下的合法子节点路径 - 存储格式错误:传入
setValue的是数组而非键值对字典,未登录状态下Auth.auth().currentUser?.uid为nil,存入数组时会直接导致字段缺失,且每次触发token回调都会生成新的自动ID节点,产生大量重复无效记录 - 缺少登录后关联逻辑:仅在获取token时执行一次写入操作,用户完成注册/登录后没有触发更新已有token记录的逻辑,自然无法把UID写入之前生成的记录中
修复方案
1. 提前初始化数据库引用
不要在token回调里才初始化ref,在AppDelegate启动或者控制器初始化阶段就完成赋值:
var ref: DatabaseReference! = Database.database().reference().child("token")
2. 修正token接收回调的存储逻辑
不要每次触发回调都新建记录,以token值为匹配依据避免重复存储,未登录时UID字段先存空字符串:
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { messaging.token { [weak self] token, error in guard let self = self, let token = token, error == nil else { return } let tokenRecord: [String: Any] = [ "Token": token, "UID": Auth.auth().currentUser?.uid ?? "" ] // 查询是否已存在当前token的记录 self.ref.queryOrdered(byChild: "Token") .queryEqual(toValue: token) .observeSingleEvent(of: .value) { snapshot in if snapshot.exists(), let existingRecord = snapshot.children.allObjects.first as? DataSnapshot { // 已有记录直接更新,不新建节点 self.ref.child(existingRecord.key).updateChildValues(tokenRecord) } else { // 无记录时新建节点 let newRecord = self.ref.childByAutoId() newRecord.setValue(tokenRecord) } } print("Current FCM Token: \(token)") } }
3. 增加注册/登录成功后的UID绑定逻辑
在处理注册成功、登录成功的回调位置,调用以下方法,把UID关联到当前设备已存的token记录上:
func updateTokenWithCurrentUid() { guard let currentUid = Auth.auth().currentUser?.uid else { return } Messaging.messaging().token { [weak self] token, error in guard let self = self, let token = token, error == nil else { return } // 匹配当前设备的token记录 self.ref.queryOrdered(byChild: "Token") .queryEqual(toValue: token) .observeSingleEvent(of: .value) { snapshot in guard snapshot.exists(), let record = snapshot.children.allObjects.first as? DataSnapshot else { return } // 只更新UID字段,不改动原有token值 self.ref.child(record.key).updateChildValues(["UID": currentUid]) } } }
最终效果
调整后数据库存储结构完全符合预期,示例如下:
"token": { "-N6tIuKBUkFpzhrEdX6f": { "Token": "cs00XevXU0WDsT2z-yginY:APA91bED3KwXRC9dXJN0iJECZu2todoD0cAO9mw_3vx3nd7WLIEkA3UkCWU4GMy5zt1iHOkOvN4OGgVZuBq12WC9LJ3o0QZyB88Rn01z7_kLdoh1ul0_opbTE-IrcZ3ylGaYuLovSfHe", "UID": "用户登录后自动补写的uid值" } }
- 用户未登录打开应用时,自动存储token,UID字段暂时为空
- 用户完成注册/登录后,自动找到对应token记录补写UID,不会生成重复数据
- FCM token刷新时会自动更新对应记录,不会出现数据不一致问题
内容的提问来源于stack exchange,提问作者Hello-World
相关产品推荐
相关产品推荐

