已解决!非常感谢 Renaud Tarnec 的原始评论引用了我尚未看到的文档。我在 Google 搜索中遗漏了关键字“存在”。如果您觉得这个答案有帮助,请点赞他的评论!
解决方案:使用https://firebase.google.com/docs/firestore/solutions/presence
斯威夫特:
var connectionReference: DatabaseReference = Database.database().reference(withPath: ".info/connected")
var personalReference: DatabaseReference?
var connectionIssued: Bool = false
func connect(room: String) {
// Remove any existing observations to ensure only one exists.
connectionReference.removeAllObservers()
// Start observing connection.
connectionReference.observe(.value) { (isConnected) in
if isConnected.value as! Bool {
// Connected!
// Use Bool connectionIssued to ensure this is run only once.
if !self.connectionIssued {
self.connectionIssued = true
self.personalReference = Database.database().reference(withPath: "OnlineUsers/\(userID)")
// Set onDisconnect before setting value.
self.personalReference!.onDisconnectRemoveValue()
self.personalReference!.setValue(room)
// Now the user is "online" and can proceed.
// Allow user to "enter" room.
} else {
// Connection already issued.
}
} else {
// The user has either disconnected from an active connection or they were already disconnected before connect() was called.
// Stop observing connection.
self.connectionReference.removeAllObservers()
// If the user disconnects after they have entered a room, kick them out.
if self.connectionIssued {
// User lost connection.
kickUserOutOfRoom()
self.connectionIssued = false
} else {
// User cannot log in.
}
}
}
}
// Call when users leave a room when still connected.
func leaveRoomManually() {
// Remove connection observation.
connectionReference.removeAllObservers()
// Attempt to remove "online" marker in database.
personalReference?.removeValue(completionBlock: { (error, reference) in
if error != nil {
// Removal failed, but that should be okay!
// onDisconnect will still be called later!
// This failure might result in ghost users if the user proceeds to join another room before disconnecting.
// Consider writing an onUpdate() cloud function in conjunction with the following onCreate() and onDelete() cloud functions to take care of that case.
} else {
// "Online" marker removed from database!
// We can now cancel the onDisconnect()
self.personalReference?.cancelDisconnectOperations()
}
})
leaveRoom()
}
云函数(javascript):
以下云函数会更新 Cloud Firestore 中各个房间的客人人数。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const firestore = admin.firestore();
exports.userCameOnline = functions.database.ref('/OnlineUsers/{userID}').onCreate(
async (snapshot, context) => {
const room = snapshot.val();
const guestCountRef = firestore.doc(`Rooms/${room}`);
return guestCountRef.update({
Guests: admin.firestore.FieldValue.increment(1)
});
});
exports.userWentOffline = functions.database.ref('/OnlineUsers/{userID}').onDelete(
async (snapshot, context) => {
const room = snapshot.val();
const guestCountRef = firestore.doc(`Rooms/${room}`);
return guestCountRef.update({
Guests: admin.firestore.FieldValue.increment(-1)
});
});