Ios Firebase:启用持久性时,如何对最新服务器数据使用observeSingleEventOfType?

Ios Firebase:启用持久性时,如何对最新服务器数据使用observeSingleEventOfType?,ios,swift,firebase,firebase-realtime-database,Ios,Swift,Firebase,Firebase Realtime Database,我真的很喜欢用Firebase编码。这是一个很棒的后端,有各种不同的工具集。但我缺少一种在启用持久性时检查更新数据路径的简单方法。我认为这不是一个罕见的用例,因为我经常需要我的应用程序根据最新的服务器数据以某种方式运行,这些数据只需要读取一次 我通常会使用observeSingleEventOfType,但当peristance被启用时,它是非常无用的,因为它是。我不明白为什么。应该添加一个选项来跳过本地缓存,只查找服务器数据 禁用持久性可以解决此问题,并且observeSingleEventO

我真的很喜欢用Firebase编码。这是一个很棒的后端,有各种不同的工具集。但我缺少一种在启用持久性时检查更新数据路径的简单方法。我认为这不是一个罕见的用例,因为我经常需要我的应用程序根据最新的服务器数据以某种方式运行,这些数据只需要读取一次

我通常会使用
observeSingleEventOfType
,但当peristance被启用时,它是非常无用的,因为它是。我不明白为什么。应该添加一个选项来跳过本地缓存,只查找服务器数据

禁用持久性可以解决此问题,并且
observeSingleEventOfType
将按预期工作。但这意味着需要自己重新实现所有离线功能

第一个场景:

 // chats contain meta information about the chat like last message and count of unread messages

 let chatRef = ref.child("chats").child(receiverId).child(chatId)
 chatRef.observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
     if !snapshot.exists() {
         print("snapshot does not exist")
         // the other side has deleted the chat
         // now delete all messages and member objects

         ref.child("messages").child(chatId).setValue(nil)
         ref.child("members").child(chatId).setValue(nil)
     } else {
         print("snapshot exists")
     }
 })
func removeOlderMessages() {
    let dateInThePast = NSDate().addDays(-30).timeIntervalSince1970 * 1000
    self.messagesRef.queryOrderedByChild("timestamp")
        .queryEndingAtValue(dateInThePast)
        .observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
            snapshot.ref.removeValue()
    })
}
在观察没有运气的事件之前,我还尝试了
chatRef.keepSynced(true)
。这并不是在所有情况下都有意义:

第二种情况:

 // chats contain meta information about the chat like last message and count of unread messages

 let chatRef = ref.child("chats").child(receiverId).child(chatId)
 chatRef.observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
     if !snapshot.exists() {
         print("snapshot does not exist")
         // the other side has deleted the chat
         // now delete all messages and member objects

         ref.child("messages").child(chatId).setValue(nil)
         ref.child("members").child(chatId).setValue(nil)
     } else {
         print("snapshot exists")
     }
 })
func removeOlderMessages() {
    let dateInThePast = NSDate().addDays(-30).timeIntervalSince1970 * 1000
    self.messagesRef.queryOrderedByChild("timestamp")
        .queryEndingAtValue(dateInThePast)
        .observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
            snapshot.ref.removeValue()
    })
}
在此处使用
keepSynced
将导致下载
messagesRef
中的所有消息,这是根本不需要的


那么,这两种情况是否有一种巧妙的解决方法?非常感谢您的帮助。

好的,我想我已经为这两种情况找到了合理的解决方法:

第一个场景的解决方法:

 // chats contain meta information about the chat like last message and count of unread messages

 let chatRef = ref.child("chats").child(receiverId).child(chatId)
 chatRef.observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
     if !snapshot.exists() {
         print("snapshot does not exist")
         // the other side has deleted the chat
         // now delete all messages and member objects

         ref.child("messages").child(chatId).setValue(nil)
         ref.child("members").child(chatId).setValue(nil)
     } else {
         print("snapshot exists")
     }
 })
func removeOlderMessages() {
    let dateInThePast = NSDate().addDays(-30).timeIntervalSince1970 * 1000
    self.messagesRef.queryOrderedByChild("timestamp")
        .queryEndingAtValue(dateInThePast)
        .observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
            snapshot.ref.removeValue()
    })
}
使用
事务
。它们只有在您在线时才起作用。
completion
块将返回最新的服务器数据

self.ref.child("chats").child(receiverId).child(chatId).runTransactionBlock({ (currentData) -> FIRTransactionResult in
    // Actually do nothing with the retrieved data and re-submit it.
    return FIRTransactionResult.successWithValue(currentData)
 }) { (error, success, snapshot) in

    if let error = error {
        print(error)
        return
    } else if !success || snapshot == nil {
       return
    }

    // snapshot contains the latest server data
    if !snapshot!.exists() {
       // the other side has deleted the chat
       // now delete all messages and member objects

       print("snapshot doesn't exist. deleting messages and members.")
       ref.child("messages").child(chatId).setValue(nil)
       ref.child("members").child(chatId).setValue(nil)     
    } else {
       print("snapshot exists. not deleting all messages and members.")
    }     
}
缺点是,与
observeEventType
observeSingleEventOfType
相比,检索数据需要更长的时间

第二种方案的变通方法:

 // chats contain meta information about the chat like last message and count of unread messages

 let chatRef = ref.child("chats").child(receiverId).child(chatId)
 chatRef.observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
     if !snapshot.exists() {
         print("snapshot does not exist")
         // the other side has deleted the chat
         // now delete all messages and member objects

         ref.child("messages").child(chatId).setValue(nil)
         ref.child("members").child(chatId).setValue(nil)
     } else {
         print("snapshot exists")
     }
 })
func removeOlderMessages() {
    let dateInThePast = NSDate().addDays(-30).timeIntervalSince1970 * 1000
    self.messagesRef.queryOrderedByChild("timestamp")
        .queryEndingAtValue(dateInThePast)
        .observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
            snapshot.ref.removeValue()
    })
}
使用
observeEventType(.Value)
。它将首先返回缓存的数据,然后返回最新的服务器数据(如果可用)。在设定的时间间隔后,可以使用
NSTimer
移除观察者


所有这些解决方法目前都还可以,但在使用
observeSingleEventOfType
时,跳过本地缓存的功能是必不可少的。

同样的问题是的,我们确实需要一个解决方案。我很好奇Firebase是否已经在开发支持此功能的功能。快速提问!当使用firebase transaction写入数据时,如果设备的internet连接在写入后立即断开,就在响应发送到客户端之前,当用户再次联机时,服务器是否会将响应发送回?例如:internet在这行
}{(错误,成功,快照)
的前面断开。另一种情况是,internet在
if!snapshot!.exists()
的前面断开。这里发生了什么?您的函数不会继续计算?所以您的应用程序将保持不一致的状态,对吗?非常感谢