Firebase: Как очистить определенные данные из firebase, когда пользователь убивает приложение?
У меня есть приложение, которое использует Firebase для базы данных, и я хочу очистить определенное поле пользователя под названием current_venue
когда пользователь убивает приложение и для этого я использую AppDelegate
метод applicationWillTerminate
и он на самом деле звонит, когда я убиваю приложение, но не полностью.
Ниже мой код в AppDelegate
:
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
WebServiceAPI.checkOutVenue()
}
И еще один метод:
static func checkOutVenue() {
WebServiceAPI.sharedInstance.current_venue = ""
if WebServiceAPI.sharedInstance.user == nil {
return
}
let user = WebServiceAPI.sharedInstance.user!
let ref = FIRDatabase.database().reference()
ref.child("Clients").child(user.uid).child("current_venue").setValue("") { (err, venueIdRef) in
if err == nil {
WebServiceAPI.sharedInstance.current_venue = ""
}
}
}
И я попытался отладить что-то вроде изображения ниже:
Когда я убиваю приложение, точка останова 1 и 2 вызывает, но оно никогда не достигает точки останова 3.
Я прочитал документацию от:
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623111-applicationwillterminate
Который говорит:
Ваша реализация этого метода имеет примерно пять секунд для выполнения любых задач и возврата. Если метод не возвращается до истечения времени, система может полностью завершить процесс.
И на самом деле не требуется более 5 секунд, чтобы очистить это поле от базы огня.
Тот же код работает нормально, когда я открываю приложение.
Так что мой код работает нормально, но есть кое-что, чего мне не хватает, когда я убиваю приложение.
Спасибо за вашу помощь.
2 ответа
Лучший способ обеспечить очистку данных при отключении пользователя - использовать onDisconnect
обработчики. Документация Firebase объясняет их, но вот простой пример того, как вы могли бы использовать его:
ref.child("Clients")
.child(user.uid)
.child("current_venue")
.onDisconnectRemoveValue()
Когда этот код выполняется, инструкция отправляется на сервер, чтобы удалить узел, когда клиент отключается. Это означает, что он всегда будет работать, даже когда клиент (или даже телефон) выходит из строя, и ваш код на стороне клиента никогда не получает шанс выполнить.
Использование асинхронной задачи в applicationWillTerminat - не лучший подход, потому что у вас есть 5 секунд, чтобы убедиться, что асинхронная задача в зависимости от силы интернет-соединения должна завершить свое выполнение (для вас это может занять менее 5 секунд для обычного пользователя). это может занять больше), иначе процесс будет убит.
Как я уже упоминал в разделе комментариев, есть еще один случай, о котором вы даже не подумали, даже если получите эту работу:
если пользователь сначала переключает приложение в фоновый режим, а после этого пытается завершить приложение, applicationWillTerminate не будет вызываться.
вы пытаетесь что-то, что теоретически невозможно
Попробуйте подумать примерно так:
func applicationDidEnterBackground(_ application: UIApplication) {
WebServiceAPI.checkOutVenue()
}