Funkcje offline na platformach Apple

Aplikacje Firebase działają nawet wtedy, gdy aplikacja tymczasowo utraci połączenie z siecią połączenia. Firebase zapewnia też narzędzia do przechowywania danych lokalnie, zarządzania obecnością i czasu oczekiwania na obsługę.

Trwałość dysku

Aplikacje Firebase automatycznie obsługują tymczasowe przerwy w działaniu sieci. Dane w pamięci podręcznej są dostępne offline, a Firebase ponownie wysyła wszystkie zapisy po przywróceniu połączenia z siecią.

Gdy włączysz trwałość dysku, aplikacja będzie zapisywać dane lokalnie w na urządzeniu, dzięki czemu aplikacja może zachowywać stan offline, nawet jeśli użytkownik lub system operacyjny ponownie uruchomi aplikację.

Trwałość dysku możesz włączyć za pomocą jednego wiersza kodu.

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
Database.database().isPersistenceEnabled = true

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
[FIRDatabase database].persistenceEnabled = YES;

Zachowanie trwałości

Jeśli włączysz trwałość, wszystkie dane udostępniane przez klienta Bazy danych czasu rzeczywistego Firebase zostanie zsynchronizowany, gdy tryb online będzie zapisany na dysku i będzie dostępny w trybie offline, nawet wtedy, gdy użytkownik lub system operacyjny ponownie uruchomi aplikację. Oznacza to, że aplikacja działa tak samo jak online, używając danych lokalnych przechowywanych w pamięci podręcznej. Wywołania zwrotne detektora będą nadal uruchamiane w przypadku aktualizacji lokalnych.

Klient Bazy danych czasu rzeczywistego Firebase automatycznie trzyma kolejkę zapisywanie operacji wykonywanych, gdy aplikacja jest offline. Gdy włączona jest trwałość, ta kolejka jest również utrwalana na dysku, więc wszystkie Twoich zapisów jest dostępne, gdy użytkownik lub system operacyjny spowoduje ponowne uruchomienie aplikacji. Gdy aplikacja odzyska połączenie, wszystkie – operacje będą wysyłane do serwera Bazy danych czasu rzeczywistego Firebase.

Jeśli aplikacja używa Uwierzytelnianie Firebase, klient Bazy danych czasu rzeczywistego Firebase utrwala uwierzytelnianie użytkownika token prywatności w przypadku ponownych uruchomień aplikacji. Jeśli token uwierzytelniania wygaśnie, gdy aplikacja będzie offline, klient zostanie wstrzymany operacji zapisu do czasu ponownego uwierzytelnienia użytkownika przez aplikację. W przeciwnym razie operacje zapisu mogą się nie powieść ze względu na reguły zabezpieczeń.

Dbanie o aktualność danych

Baza danych czasu rzeczywistego Firebase synchronizuje i przechowuje lokalną kopię bazy danych w przypadku aktywnych detektorów. Możesz też zachować określone lokalizacje zsynchronizowane.

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
let scoresRef = Database.database().reference(withPath: "scores")
scoresRef.keepSynced(true)

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
FIRDatabaseReference *scoresRef = [[FIRDatabase database] referenceWithPath:@"scores"];
[scoresRef keepSynced:YES];

Klient Bazy danych czasu rzeczywistego Firebase automatycznie pobiera dane ze te lokalizacje i jest synchronizowana, nawet jeśli w pliku referencyjnym nie ma aktywnych detektorów. Synchronizację możesz wyłączyć ponownie, w tym wierszu.

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
scoresRef.keepSynced(false)

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
[scoresRef keepSynced:NO];

Domyślnie w pamięci podręcznej przechowywane jest 10 MB wcześniej zsynchronizowanych danych. Powinien to być która wystarcza do większości zastosowań. Jeśli pamięć podręczna przepełni swój skonfigurowany rozmiar, Baza danych czasu rzeczywistego Firebase trwale usuwa dane, które były ostatnio używane. Zsynchronizowane dane nie są trwale usuwane z pamięci podręcznej.

Wysyłanie zapytań o dane offline

Baza danych czasu rzeczywistego Firebase przechowuje w celu użycia dane zwrócone z zapytania gdy jesteś offline. W przypadku zapytań utworzonych w trybie offline Baza danych czasu rzeczywistego Firebase działa z danymi wczytanymi wcześniej. Jeśli żądane dane nie zostały wczytane, Baza danych czasu rzeczywistego Firebase zostanie wczytana. z lokalnej pamięci podręcznej. Gdy połączenie sieciowe będzie znów dostępne, dane zostaną wczytane i będą odzwierciedlały zapytanie.

Na przykład ten kod wysyła zapytania dotyczące ostatnich cztery elementy w Bazie danych czasu rzeczywistego Firebase z wynikami

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
let scoresRef = Database.database().reference(withPath: "scores")
scoresRef.queryOrderedByValue().queryLimited(toLast: 4).observe(.childAdded) { snapshot in
  print("The \(snapshot.key) dinosaur's score is \(snapshot.value ?? "null")")
}

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
FIRDatabaseReference *scoresRef = [[FIRDatabase database] referenceWithPath:@"scores"];
[[[scoresRef queryOrderedByValue] queryLimitedToLast:4]
    observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
      NSLog(@"The %@ dinosaur's score is %@", snapshot.key, snapshot.value);
    }];

Załóżmy, że użytkownik traci połączenie, przechodzi w tryb offline i ponownie uruchamia aplikację. Będąc w trybie offline, aplikacja wysyła zapytanie o ostatnie 2 elementy z w tej samej lokalizacji. To zapytanie zwróci 2 ostatnie elementy bo aplikacja wczytała wszystkie 4 elementy w powyższym zapytaniu.

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
scoresRef.queryOrderedByValue().queryLimited(toLast: 2).observe(.childAdded) { snapshot in
  print("The \(snapshot.key) dinosaur's score is \(snapshot.value ?? "null")")
}

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
[[[scoresRef queryOrderedByValue] queryLimitedToLast:2]
    observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
      NSLog(@"The %@ dinosaur's score is %@", snapshot.key, snapshot.value);
    }];

W poprzednim przykładzie klient Bazy danych czasu rzeczywistego Firebase generuje „dodano dziecko” dla najlepszych wyników dwóch dinozaurów, wykorzystując utrwalonej pamięci podręcznej. Nie spowoduje to jednak zwiększenia „wartości” zdarzenia, bo aplikacja nigdy nie wykonał tego zapytania w trybie online.

Gdyby w trybie offline aplikacja zażądała ostatnich 6 elementów, otrzyma żądanie „dodano dziecko” dla czterech elementów w pamięci podręcznej. Gdy urządzenie powraca online, klient Bazy danych czasu rzeczywistego Firebase synchronizuje się z serwerem i otrzymuje dwa ostatnie atrybuty „podrzędne” oraz „value” zdarzeń dla aplikacji.

Obsługa transakcji offline

Wszystkie transakcje wykonane, gdy aplikacja jest offline, są umieszczane w kolejce. Gdy aplikacja odzyska połączenie z siecią, transakcje zostaną przesłane do na serwerze Bazy danych czasu rzeczywistego.

Zarządzanie obecnością

W aplikacjach działających w czasie rzeczywistym często przydaje się możliwość wykrywania, nawiąż i rozłącz. Możesz na przykład chcesz oznaczyć użytkownika jako użytkownika offline. gdy klient się rozłącza.

Klienty bazy danych Firebase udostępniają proste elementy podstawowe umożliwiające zapisywanie w bazie danych, gdy klient odłączy się od bazy danych Firebase serwerów. Te aktualizacje pojawiają się niezależnie od tego, czy klient się rozłącza, czy nie, Możesz na nich polegać, jeśli wyczyścisz dane nawet wtedy, gdy połączenie zostanie przerwane lub po awarii klienta. Wszystkie operacje zapisu, w tym ustawienia aktualizacji i usuwania można przeprowadzić po rozłączeniu.

Oto prosty przykład zapisywania danych po odłączeniu za pomocą polecenia Element podstawowy onDisconnect:

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
let presenceRef = Database.database().reference(withPath: "disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnectSetValue("I disconnected!")

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
FIRDatabaseReference *presenceRef = [[FIRDatabase database] referenceWithPath:@"disconnectmessage"];
// Write a string when this client loses connection
[presenceRef onDisconnectSetValue:@"I disconnected!"];

Jak onOdłącz działa?

Gdy utworzysz operację onDisconnect(), działa na serwerze Bazy danych czasu rzeczywistego Firebase. Serwer sprawdza zabezpieczenia Upewnij się, że użytkownik może wykonać żądane zdarzenie zapisu oraz informuje aplikacji, jeśli jest ona nieprawidłowa. Serwer oraz monitoruje połączenie. jeśli w którymkolwiek momencie połączenie zostanie przekroczone lub będzie aktywnie zamkniętego przez klienta Bazy danych czasu rzeczywistego, serwer sprawdza zabezpieczenia po raz drugi (aby upewnić się, że operacja jest nadal prawidłowa), a następnie wywołuje do zdarzenia.

Aplikacja może używać wywołania zwrotnego podczas zapisu aby upewnić się, że łącznik onDisconnect został prawidłowo podłączony:

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
presenceRef.onDisconnectRemoveValue { error, reference in
  if let error = error {
    print("Could not establish onDisconnect event: \(error)")
  }
}

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
[presenceRef onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *reference) {
  if (error != nil) {
    NSLog(@"Could not establish onDisconnect event: %@", error);
  }
}];

Wydarzenie onDisconnect można też anulować, dzwoniąc pod numer .cancel():

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
presenceRef.onDisconnectSetValue("I disconnected")
// some time later when we change our minds
presenceRef.cancelDisconnectOperations()

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
[presenceRef onDisconnectSetValue:@"I disconnected"];
// some time later when we change our minds
[presenceRef cancelDisconnectOperations];

Wykrywam stan połączenia

W przypadku wielu funkcji związanych z obecnością opcja jest przydatna w aplikacji czy jest online czy offline. Baza danych czasu rzeczywistego Firebase udostępnia specjalną lokalizację pod adresem /.info/connected, która jest aktualizowany za każdym razem, gdy stan połączenia klienta Bazy danych czasu rzeczywistego Firebase jest aktualizowany zmian. Oto przykład:

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
let connectedRef = Database.database().reference(withPath: ".info/connected")
connectedRef.observe(.value, with: { snapshot in
  if snapshot.value as? Bool ?? false {
    print("Connected")
  } else {
    print("Not connected")
  }
})

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
FIRDatabaseReference *connectedRef = [[FIRDatabase database] referenceWithPath:@".info/connected"];
[connectedRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  if([snapshot.value boolValue]) {
    NSLog(@"connected");
  } else {
    NSLog(@"not connected");
  }
}];

/.info/connected jest wartością logiczną, która nie jest jest synchronizowana między klientami Bazy danych czasu rzeczywistego, ponieważ wartość to w zależności od stanu klienta. Innymi słowy, jeśli jeden klient odczytuje /.info/connected jako fałsz, to nie jest zagwarantowanie, że oddzielny klient również odczyta wartość „false” (fałsz).

Czas oczekiwania na obsługę

Sygnatury czasowe serwera

Serwery Bazy danych czasu rzeczywistego Firebase oferują mechanizm wstawiania sygnatur czasowych wygenerowanych na serwerze jako dane. Ta funkcja w połączeniu z onDisconnect umożliwia łatwe zanotowanie moment odłączenia klienta Bazy danych czasu rzeczywistego:

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
let userLastOnlineRef = Database.database().reference(withPath: "users/morgan/lastOnline")
userLastOnlineRef.onDisconnectSetValue(ServerValue.timestamp())

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
FIRDatabaseReference *userLastOnlineRef = [[FIRDatabase database] referenceWithPath:@"users/morgan/lastOnline"];
[userLastOnlineRef onDisconnectSetValue:[FIRServerValue timestamp]];

Zniekształcenie zegara

firebase.database.ServerValue.TIMESTAMP to znacznie więcej dokładne i zalecane w większości operacji odczytu/zapisu, czasami może być przydatne do oszacowania zniekształcenia zegara klienta, w kontekście serwerów Bazy danych czasu rzeczywistego Firebase. Ty może dołączyć oddzwonienie do lokalizacji /.info/serverTimeOffset aby uzyskać w milisekundach wartość klientów Bazy danych czasu rzeczywistego Firebase dodaj do szacunkowego czasu raportowania lokalnego (czasu epoki w milisekundach) czas serwera. Pamiętaj, że na dokładność przesunięcia może mieć wpływ opóźnienia sieciowe, co przydaje się przede wszystkim do wykrywania duże (> 1 sekundę) rozbieżności w czasie zegara.

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
let offsetRef = Database.database().reference(withPath: ".info/serverTimeOffset")
offsetRef.observe(.value, with: { snapshot in
  if let offset = snapshot.value as? TimeInterval {
    print("Estimated server time in milliseconds: \(Date().timeIntervalSince1970 * 1000 + offset)")
  }
})

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
FIRDatabaseReference *offsetRef = [[FIRDatabase database] referenceWithPath:@".info/serverTimeOffset"];
[offsetRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  NSTimeInterval offset = [(NSNumber *)snapshot.value doubleValue];
  NSTimeInterval estimatedServerTimeMs = [[NSDate date] timeIntervalSince1970] * 1000.0 + offset;
  NSLog(@"Estimated server time: %0.3f", estimatedServerTimeMs);
}];

Przykładowa aplikacja Obecność

Łącząc operacje rozłączania z monitorowaniem stanu połączenia sygnatury czasowe serwera, możesz utworzyć system wykrywania obecności użytkowników. W tym systemie każdy użytkownik przechowuje dane w lokalizacji bazy danych, aby wskazać, czy Klient Bazy danych czasu rzeczywistego jest online. Klienci ustawili tę lokalizację na Prawda, gdy: kiedy przechodzą do trybu online, oraz podaj sygnaturę czasową po rozłączeniu. Ta sygnatura czasowa wskazuje, kiedy dany użytkownik ostatnio był online.

Pamiętaj, że aplikacja powinna zakoleć operacje rozłączania, zanim użytkownik oznaczone jako online, co pozwala uniknąć wyścigów w przypadku, gdy utracisz połączenie sieciowe, zanim możliwe będzie wysłanie obu poleceń do serwera.

Oto prosty system wykrywania obecności użytkowników:

Swift

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
// since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
let myConnectionsRef = Database.database().reference(withPath: "users/morgan/connections")

// stores the timestamp of my last disconnect (the last time I was seen online)
let lastOnlineRef = Database.database().reference(withPath: "users/morgan/lastOnline")

let connectedRef = Database.database().reference(withPath: ".info/connected")

connectedRef.observe(.value, with: { snapshot in
  // only handle connection established (or I've reconnected after a loss of connection)
  guard snapshot.value as? Bool ?? false else { return }

  // add this device to my connections list
  let con = myConnectionsRef.childByAutoId()

  // when this device disconnects, remove it.
  con.onDisconnectRemoveValue()

  // The onDisconnect() call is before the call to set() itself. This is to avoid a race condition
  // where you set the user's presence to true and the client disconnects before the
  // onDisconnect() operation takes effect, leaving a ghost user.

  // this value could contain info about the device or a timestamp instead of just true
  con.setValue(true)

  // when I disconnect, update the last time I was seen online
  lastOnlineRef.onDisconnectSetValue(ServerValue.timestamp())
})

Objective-C

Uwaga: ta usługa Firebase nie jest dostępna w celu wycinka aplikacji.
// since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
FIRDatabaseReference *myConnectionsRef = [[FIRDatabase database] referenceWithPath:@"users/morgan/connections"];

// stores the timestamp of my last disconnect (the last time I was seen online)
FIRDatabaseReference *lastOnlineRef = [[FIRDatabase database] referenceWithPath:@"users/morgan/lastOnline"];

FIRDatabaseReference *connectedRef = [[FIRDatabase database] referenceWithPath:@".info/connected"];
[connectedRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  if([snapshot.value boolValue]) {
    // connection established (or I've reconnected after a loss of connection)

    // add this device to my connections list
    FIRDatabaseReference *con = [myConnectionsRef childByAutoId];

    // when this device disconnects, remove it
    [con onDisconnectRemoveValue];

    // The onDisconnect() call is before the call to set() itself. This is to avoid a race condition
    // where you set the user's presence to true and the client disconnects before the
    // onDisconnect() operation takes effect, leaving a ghost user.

    // this value could contain info about the device or a timestamp instead of just true
    [con setValue:@YES];


    // when I disconnect, update the last time I was seen online
    [lastOnlineRef onDisconnectSetValue:[FIRServerValue timestamp]];
  }
}];