1

我使用Firebase离线功能,特别是使用它来确定用户何时上线或他在线。在测试过程中,我遇到了这样的问题,即如果我注销,断开连接功能不起作用,但我不取消断开连接功能。我明白,在注销之前,我可以自己发送这些数据,但这个功能的含义将从框中消失。告诉我如何解决这个问题?iOS上的Firebase离线功能

该函数确定用户的活动和我称之为在MainTabBarController(它被用作根控制器)

func setupLastSeenActivity() { 
     DispatchQueue.main.async { 
      let realmManager = RealmManager() 
      guard let currentUserID = realmManager.getCurrentUser()?.id else { return } 
      DispatchQueue.global(qos: .background).async { 
       let ref = Database.database().reference().child(MainGateways.users.rawValue).child(currentUserID) 
       let userSearchLocationRef = Database.database().reference().child(UserSearchLocationKeys.userSearchLocationModel.rawValue).child(currentUserID) 

       let parameters = [UserSubgateways.isOnline.rawValue : true] 
       ref.updateChildValues(parameters, withCompletionBlock: { (error, ref) in 

       }) 

       userSearchLocationRef.updateChildValues(parameters, withCompletionBlock: { (error, ref) in 

       }) 

       let disconnectParameters = [UserSubgateways.isOnline.rawValue : false, UserSubgateways.lastSeenTimeStamp.rawValue : ServerValue.timestamp()] as [String : Any] 

       ref.onDisconnectUpdateChildValues(disconnectParameters, withCompletionBlock: { (error, ref) in 
        guard let _error = error else { return } 
        debugPrint(_error.localizedDescription) 
       }) 

       userSearchLocationRef.onDisconnectUpdateChildValues(disconnectParameters, withCompletionBlock: { (error, ref) in 
        guard let _error = error else { return } 
        debugPrint(_error.localizedDescription) 
       }) 
      } 
     } 
    } 

FirebaseAuthManager

func logOut(completion: (() -> Void)?) { 
     DispatchQueue.main.async { 
      do { 
       let pushNotificationManager = PushNotificationManager() 
       pushNotificationManager.unregisterPushNotification() 
       pushNotificationManager.removeTokenWhenLogOut(success: nil) 
       // Observers 
       FIRFriendsDatabaseManager.shared.observeNewFriend(false, success: nil, fail: nil) 
       FIRFriendsDatabaseManager.shared.observeFriendRemoved(false, success: nil, fail: nil) 
       let firChatCardManager = FIRChatCardManager() 
       firChatCardManager.syncChatCardModels(false) 

       FacebookManager.logOut() 
       Database.database().reference().removeAllObservers() 

       let firebaseGeneralDatabaseManager = FirebaseDatabaseGeneralManager() 
       firebaseGeneralDatabaseManager.logOut() 
       try Auth.auth().signOut() 
       let realmManager = RealmManager() 
       realmManager.logOut() 
       let appManager = AppManager() 
       appManager.logOut(isDeleteAccount: false, completion: completion) 
      } catch { 
       debugPrint(error.localizedDescription) 
      } 
     } 
    } 
+0

用户可以在未登录的情况下连接。用户可以在未连接的情况下登录。两者都是正常和预期的行为。你想用onDisconnect处理器实现的具体用例是什么? –

+0

@FrankvanPuffelen我试图实现正确反映用户状态的可能性,即在线/离线。但是我也认为onDisconnect处理程序对于这种情况并不理想,因为用户可以从多个设备登录到他的帐户,例如,只有一个设备会丢失Internet连接。告诉我,Firebase会考虑每个用户的连接数量,如果是这样,请在哪里查找有关如何使用它的信息。 – Alexander

+0

[文档中的状态示例](https://firebase.google.com/docs/database/ios/offline-capabilities#section-sample)会跟踪每个用户的多个连接,正是由于这个原因。 –

回答

0

甲注销功能我由云功能如果连接的设备数量为0,则计数连接的设备数量,然后设置值isOnline = false并设置lastSeenTimeStamp

const functions = require('firebase-functions'); 
const admin = require('firebase-admin'); 

module.exports = functions.database.ref('userOnlineDevices/{userID}/{onlineSystemModelID}') 
    .onWrite(event => { 

     const snapshot = event.data; 
     const userID = event.params.userID; 
     const onlineSystemModelID = event.params.onlineSystemModelID; 

     const currentData = event.data.current; 
     const previousData = event.data.previous; 

     console.log("currentData.val()", currentData.val(), "previousData.val()", previousData.val()); 

     if (currentData.val() && !previousData.val()) { 
      // value created 

      const checkUserRef = admin.database().ref("users").child(userID); 
      const checkUserRefPromise = checkUserRef.once("value", function(checkUserRefSnap, error) { 
       if (error) { 
        return console.log("created checkUserRefPromise error", error); 
       } 
       if (checkUserRefSnap.val()) { 
        const checkUserID = checkUserRefSnap.val()["id"]; 
        if (checkUserID == null) { 
         return console.log("checkUserID == null") 
        } else { 
         console.log("checkUserID", checkUserID) 
        } 

        const recentActivityTimeStamp = Math.floor(Date.now()/1000); 
        const userRef = admin.database().ref("users").child(userID); 
        const userRefPromise = userRef.update({ 
         "isOnline": true 
        }); 

        const userSearchLocationModelRef = admin.database().ref("userSearchLocationModel").child(userID); 
        const userSearchLocationModelRefPromise = userSearchLocationModelRef.update({ 
         "isOnline": true, 
         "recentActivityTimeStamp": recentActivityTimeStamp 
        }); 

        return Promise.all([userRefPromise, userSearchLocationModelRefPromise]); 
       } else { 
        return console.log("checkUserRefSnap.val() == null") 
       } 
      }); 

      return Promise.all([checkUserRefPromise]); 
     } else if (!currentData.val() && previousData.val()) { 
      // value removed 
      const checkUserRef = admin.database().ref("users").child(userID); 
      const checkUserRefPromise = checkUserRef.once("value", function(checkUserRefSnap, error) { 
       if (error) { 
        return console.log(error); 
       } 

       if (checkUserRefSnap.val()) { 
        const checkUserID = checkUserRefSnap.val()["id"]; 
        if (checkUserID == null) { 
         return console.log("checkUserID == null") 
        } else { 
         console.log("checkUserID", checkUserID) 
        } 

        if (userID) { 
         const removedTimeStamp = new Date()/1000; 
         const userRef = admin.database().ref("users").child(userID); 
         const userRefPromise = userRef.update({ 
          "isOnline": false, 
          "lastSeenTimeStamp": removedTimeStamp 
         }); 

         const userSearchLocationModelRef = admin.database().ref("userSearchLocationModel").child(userID); 
         const userSearchLocationModelRefPromise = userSearchLocationModelRef.update({ 
          "isOnline": false, 
          "lastSeenTimeStamp": removedTimeStamp 
         }); 

         return Promise.all([userRefPromise, userSearchLocationModelRefPromise]); 
        } else { 
         return console.log("removed, userID == null"); 
        } 
       } else { 
        return console.log("removed, checkUserRefSnap.val() == null"); 
       } 
      }); 

      return Promise.all([checkUserRefPromise]); 
     } else { 
      // updated 
      const checkUserRef = admin.database().ref("users").child(userID); 
      const checkUserRefPromise = checkUserRef.once("value", function(checkUserRefSnap, error) { 
       if (error) { 
        return console.log(error); 
       } 

       if (checkUserRefSnap.val()) { 
        const checkUserID = checkUserRefSnap.val()["id"]; 
        if (checkUserID == null) { 
         return console.log("checkUserID == null") 
        } else { 
         console.log("checkUserID", checkUserID) 
        } 

        const recentActivityTimeStamp = Math.floor(Date.now()/1000); 
        const userRef = admin.database().ref("users").child(userID); 
        const userRefPromise = userRef.update({ 
         "isOnline": true 
        }); 

        const userSearchLocationModelRef = admin.database().ref("userSearchLocationModel").child(userID); 
        const userSearchLocationModelRefPromise = userSearchLocationModelRef.update({ 
         "isOnline": true, 
         "recentActivityTimeStamp": recentActivityTimeStamp 
        }); 

        return Promise.all([userRefPromise, userSearchLocationModelRefPromise]); 
       } else { 
        return console.log("updated checkUserRefSnap.val() == null"); 
       } 
      }); 

      return Promise.all([checkUserRefPromise]); 
     } 
    });