Firebase: как использовать функцию observSingleEventOfType для получения последних данных сервера при включенной поддержке?
Мне очень нравится кодирование с Firebase. Это отличный бэкэнд с множеством различных наборов инструментов. Но я пропустил простой способ проверить путь для обновленных данных, когда включено. Я думаю, что это не редкость, потому что мне часто нужно, чтобы мое приложение действовало определенным образом в зависимости от последних данных сервера, которые нужно читать только один раз.
Обычно я использую observeSingleEventOfType
, но это бесполезно, когда разрешена поддержка, так как никогда не будет извлекать последние данные сервера. Который я не понимаю, почему. Должна быть добавлена опция, чтобы пропустить локальный кеш и посмотреть только данные сервера.
Отключение стойкости решает эту проблему, а 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")
}
})
Я также пробовал chatRef.keepSynced(true)
, прежде чем наблюдать за событиями без везения. В любом случае это не имеет смысла во всех ситуациях:
Второй сценарий:
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
, что совсем не требуется.
Итак, есть ли умное решение для этих двух сценариев? Любая помощь приветствуется.
Ответы
Ответ 1
Хорошо, думаю, я нашел разумное решение для обоих сценариев:
Обходной путь для первого сценария:
Используйте transactions
. Они будут работать только в режиме онлайн. Блок completition
будет возвращать последние данные сервера.
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
.
Обходной путь для второго сценария:
Используйте observeEventType(.Value)
. Сначала он будет возвращать кэшированные, а затем последние данные сервера, если они доступны. Наблюдатель может быть удален после заданного интервала времени с NSTimer
.
Во всех этих обходных решениях все нормально, но функция пропустить локальный кеш при использовании observeSingleEventOfType
является незаменимой.