iOS端Firebase实现添加记录用户自收推送(基于UID)
解决Firebase仅向操作用户发送推送通知的问题
刚接触Firebase碰到这个推送范围的问题太正常啦,主题推送本来就是给所有订阅主题的用户广播消息,所以才会出现全员收到的情况。要实现只给操作添加记录的那个用户发通知,核心思路就是针对单个用户的设备令牌发送定向推送,下面给你一步步拆解实现方法:
1. 绑定存储用户的FCM设备令牌与账号
首先得让每个登录用户的设备令牌和他的Firebase Auth UID关联起来,存到数据库里,这样后续才能精准找到要推送的目标。
在iOS端获取并存储令牌的代码示例:
import FirebaseMessaging import FirebaseAuth func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { // 关联APNs令牌和FCM Messaging.messaging().apnsToken = deviceToken // 获取FCM令牌 Messaging.messaging().token { token, error in if let error = error { print("获取FCM令牌失败:\(error.localizedDescription)") return } guard let token = token, let currentUserUID = Auth.auth().currentUser?.uid else { print("用户未登录或令牌获取失败") return } // 将令牌存入Firebase数据库,关联当前用户UID let userTokenRef = Database.database().reference() .child("users") .child(currentUserUID) .child("fcmToken") userTokenRef.setValue(token) { error, _ in if let error = error { print("存储令牌失败:\(error.localizedDescription)") } else { print("令牌存储成功") } } } }
注意:FCM令牌可能会不定期更新,建议在App启动时也检查更新一次令牌,保证数据库里的令牌是最新的。
2. 添加记录时存入操作用户的UID
在客户端添加记录的逻辑里,一定要把当前登录用户的UID一起存入记录中,这样后续Cloud Functions才能知道这条记录是谁加的,找到对应的推送令牌。
iOS端添加记录的代码示例:
import FirebaseDatabase import FirebaseAuth func addNewRecord(content: String) { guard let currentUserUID = Auth.auth().currentUser?.uid else { print("用户未登录,无法添加记录") return } // 生成新记录的节点 let newRecordRef = Database.database().reference() .child("records") .childByAutoId() // 记录数据包含内容和添加者UID let recordData: [String: Any] = [ "content": content, "addedBy": currentUserUID ] // 写入数据库 newRecordRef.setValue(recordData) { error, _ in if let error = error { print("添加记录失败:\(error.localizedDescription)") } else { print("记录添加成功") } } }
3. 用Firebase Cloud Functions触发定向推送
直接在客户端发推送不安全(会暴露FCM API密钥),所以推荐用Cloud Functions,当数据库里有新记录创建时,自动触发推送逻辑,找到对应用户的令牌发通知。
编写Cloud Functions的Node.js代码:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); // 当records节点下有新记录创建时触发 exports.sendRecordAddedNotification = functions.database.ref('/records/{recordId}') .onCreate(async (snapshot, context) => { // 获取添加记录的用户UID const addedByUID = snapshot.val().addedBy; if (!addedByUID) { functions.logger.info("记录中未包含添加者UID,跳过推送"); return null; } // 从数据库获取该用户的FCM令牌 const tokenSnapshot = await admin.database().ref(`/users/${addedByUID}/fcmToken`).once('value'); const fcmToken = tokenSnapshot.val(); if (!fcmToken) { functions.logger.info("未找到该用户的FCM令牌,跳过推送"); return null; } // 构建推送内容 const payload = { notification: { title: "记录已添加", body: "你成功创建了一条新记录" }, token: fcmToken }; // 发送推送 try { await admin.messaging().send(payload); functions.logger.info("推送发送成功"); } catch (error) { functions.logger.error("推送发送失败:", error); } return null; });
写完代码后,用
firebase deploy --only functions命令部署到Firebase即可。
额外注意事项
- 确保iOS端已经正确配置了APNs证书和Firebase推送设置,不然即使推送发送成功,设备也收不到通知。
- 如果用户有多台设备,可以在数据库里存储一个令牌数组,推送时遍历数组发送给所有关联设备。
- 权限方面,Cloud Functions默认的服务账号权限足够访问数据库和发送FCM,如果遇到权限问题,可以去Firebase控制台的IAM页面检查配置。
内容的提问来源于stack exchange,提问作者Oliver Ferris
相关产品推荐
相关产品推荐

