Google is committed to advancing racial equity for Black communities. See how.
Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Przeprowadź migrację aplikacji Parse na iOS do Firebase

Jeśli jesteś użytkownikiem analizowania i szukasz alternatywnego rozwiązania Backend as a Service, Firebase może być idealnym wyborem dla Twojej aplikacji na iOS.

W tym przewodniku opisano, jak zintegrować określone usługi z aplikacją. Aby uzyskać podstawowe instrukcje konfiguracji Firebase, zapoznaj się z instrukcją konfiguracji iOS .

Google Analytics

Google Analytics to bezpłatne rozwiązanie do pomiaru aplikacji, które zapewnia wgląd w wykorzystanie aplikacji i zaangażowanie użytkowników. Analytics integruje się z funkcjami Firebase i zapewnia nieograniczone raportowanie do 500 różnych zdarzeń, które można zdefiniować za pomocą pakietu Firebase SDK.

Zobacz dokumentację Google Analytics, aby dowiedzieć się więcej.

Sugerowana strategia migracji

Korzystanie z różnych dostawców usług analitycznych to typowy scenariusz, który można łatwo zastosować w Google Analytics. Po prostu dodaj go do swojej aplikacji, aby korzystać ze zdarzeń i właściwości użytkownika, które Analytics zbiera automatycznie, takich jak pierwsze uruchomienie, aktualizacja aplikacji, model urządzenia, wiek.

W przypadku zdarzeń niestandardowych i właściwości użytkownika można zastosować strategię podwójnego zapisu, korzystając zarówno z analizy Parse Analytics, jak i Google Analytics do rejestrowania zdarzeń i właściwości, co umożliwia stopniowe wdrażanie nowego rozwiązania.

Porównanie kodów

Analiza analizy

 // Start collecting data
[PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions];

NSDictionary *dimensions = @{
  // Define ranges to bucket data points into meaningful segments
  @"priceRange": @"1000-1500",
  // Did the user filter the query?
  @"source": @"craigslist",
  // Do searches happen more often on weekdays or weekends?
  @"dayType": @"weekday"
};
// Send the dimensions to Parse along with the 'search' event
[PFAnalytics trackEvent:@"search" dimensions:dimensions];
 

Google Analytics

 // Obtain the AppMeasurement instance and start collecting data
[FIRApp configure];

// Send the event with your params
[FIRAnalytics logEventWithName:@"search" parameters:@{
  // Define ranges to bucket data points into meaningful segments
  @"priceRange": @"1000-1500",
  // Did the user filter the query?
  @"source": @"craigslist",
  // Do searches happen more often on weekdays or weekends?
  @"dayType": @"weekday"
}];
 

Baza danych czasu rzeczywistego Firebase

Baza danych czasu rzeczywistego Firebase to baza danych NoSQL hostowana w chmurze. Dane są przechowywane w formacie JSON i synchronizowane w czasie rzeczywistym z każdym podłączonym klientem.

Więcej informacji można znaleźć w dokumentacji Bazy danych czasu rzeczywistego Firebase .

Różnice w analizie danych

Obiekty

W Parse przechowujesz obiekt PFObject lub jego podklasę, która zawiera pary klucz-wartość danych zgodnych z JSON. Dane nie mają schematu, co oznacza, że ​​nie musisz określać, jakie klucze istnieją na każdym PFObject .

Wszystkie dane Firebase Realtime Database są przechowywane jako obiekty JSON i nie ma odpowiednika dla PFObject ; po prostu piszesz w drzewie JSON wartości typów, które odpowiadają dostępnym typom JSON.

Poniżej znajduje się przykład, w jaki sposób możesz zapisać najlepsze wyniki z gry.

Analizować
 PFObject *gameScore = [PFObject objectWithClassName:@"GameScore"];
gameScore[@"score"] = @1337;
gameScore[@"playerName"] = @"Sean Plott";
gameScore[@"cheatMode"] = @NO;
[gameScore saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
  if (succeeded) {
    // The object has been saved.
  } else {
    // There was a problem, check error.description
  }
}];
 
Firebase
 // Create a reference to the database
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
NSString *key = [[ref child:@"scores"] childByAutoId].key;
NSDictionary *score = @{@"score": @1337,
                        @"playerName": @"Sean Plott",
                        @"cheatMode": @NO};
[key setValue:score withCompletionBlock:^(NSError *error,  FIRDatabaseReference *ref) {
  if (error) {
    // The object has been saved.
  } else {
    // There was a problem, check error.description
  }
}];
 
Aby uzyskać więcej informacji, zapoznaj się z przewodnikiem dotyczącym odczytu i zapisu danych w systemie iOS .

Relacje między danymi

PFObject może mieć relację z innym PFObject : każdy obiekt może używać innych obiektów jako wartości.

W bazie danych czasu rzeczywistego Firebase relacje są lepiej wyrażane za pomocą płaskich struktur danych, które dzielą dane na oddzielne ścieżki, dzięki czemu można je wydajnie pobierać w oddzielnych wywołaniach.

Poniżej znajduje się przykład struktury relacji między postami w aplikacji do blogowania a ich autorami.

Analizować
 // Create the author
PFObject *myAuthor = [PFObject objectWithClassName:@"Author"];
myAuthor[@"name"] = @"Grace Hopper";
myAuthor[@"birthDate"] = @"December 9, 1906";
myAuthor[@"nickname"] = @"Amazing Grace";

// Create the post
PFObject *myPost = [PFObject objectWithClassName:@"Post"];
myPost[@"title"] = @"Announcing COBOL, a New Programming Language";

// Add a relation between the Post and the Author
myPost[@"parent"] = myAuthor;

// This will save both myAuthor and myPost
[myPost saveInBackground];
 
Firebase
 // Create a reference to the database
FIRDatabaseReference *ref = [[FIRDatabase database] reference];

// Create the author
NSString *myAuthorKey = @"ghopper";
NSDictionary *author = @{@"name": @"Grace Hopper",
                         @"birthDate": @"December 9, 1906",
                         @"nickname": @"Amazing Grace"};
// Save the author
[[ref child:myAuthorKey] setValue:author]

// Create and save the post
NSString *key = [[ref child:@"posts"] childByAutoId].key;
NSDictionary *post = @{@"author": myAuthorKey,
                       @"title": @"Announcing COBOL, a New Programming Language"};
[key setValue:post]
 

Wynikiem jest następujący układ danych.

{
  // Info about the authors
  "authors": {
    "ghopper": {
      "name": "Grace Hopper",
      "date_of_birth": "December 9, 1906",
      "nickname": "Amazing Grace"
    },
    ...
  },
  // Info about the posts: the "author" fields contains the key for the author
  "posts": {
    "-JRHTHaIs-jNPLXOQivY": {
      "author": "ghopper",
      "title": "Announcing COBOL, a New Programming Language"
    }
    ...
  }
}
Aby uzyskać więcej informacji, zapoznaj się z przewodnikiem Structure Your Database .

Czytanie danych

W Parse odczytujesz dane przy użyciu identyfikatora określonego obiektu Parse lub wykonując zapytania przy użyciu PFQuery .

W Firebase pobierasz dane, dołączając odbiornik asynchroniczny do odwołania do bazy danych. Odbiornik jest wyzwalany raz dla początkowego stanu danych i ponownie, gdy dane ulegną zmianie, więc nie trzeba dodawać żadnego kodu, aby określić, czy dane uległy zmianie.

Poniżej znajduje się przykład, w jaki sposób można pobrać wyniki dla konkretnego gracza, na podstawie przykładu przedstawionego w sekcji „Obiekty” .

Analizować
 PFQuery *query = [PFQuery queryWithClassName:@"GameScore"];
[query whereKey:@"playerName" equalTo:@"Dan Stemkoski"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
  if (!error) {
    for (PFObject *score in objects) {
      NSString *gameScore = score[@"score"];
      NSLog(@"Retrieved: %@", gameScore);
    }
  } else {
    // Log details of the failure
    NSLog(@"Error: %@ %@", error, [error userInfo]);
  }
}];
 
Firebase
 // Create a reference to the database
FIRDatabaseReference *ref = [[FIRDatabase database] reference];

// This type of listener is not one time, and you need to cancel it to stop
// receiving updates.
[[[[ref child:@"scores"] queryOrderedByChild:@"playerName"] queryEqualToValue:@"Dan Stemkoski"]
    observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
  // This will fire for each matching child node.
  NSDictionary *score = snapshot.value;
  NSString gameScore = score[@"score"];
  NSLog(@"Retrieved: %@", gameScore);
}];
 
Aby uzyskać więcej informacji na temat dostępnych typów detektorów zdarzeń oraz sposobu porządkowania i filtrowania danych, zapoznaj się z przewodnikiem dotyczącym odczytu i zapisu danych w systemie iOS .

Sugerowana strategia migracji

Przemyśl swoje dane

Baza danych czasu rzeczywistego Firebase jest zoptymalizowana pod kątem synchronizowania danych w milisekundach na wszystkich połączonych klientach, a wynikowa struktura danych różni się od podstawowych danych Parse. Oznacza to, że pierwszym krokiem migracji jest rozważenie, jakich zmian wymagają dane, w tym:

  • Jak obiekty Parse powinny być mapowane na dane Firebase
  • Jeśli masz relacje rodzic-dziecko, jak podzielić dane na różne ścieżki, aby można je było efektywnie pobierać w oddzielnych wywołaniach.

Przenieś swoje dane

Po podjęciu decyzji, jak uporządkować dane w Firebase, musisz zaplanować, jak obsłużyć okres, w którym aplikacja musi zapisywać dane w obu bazach danych. Masz do wyboru:

Synchronizacja w tle

W tym scenariuszu masz dwie wersje aplikacji: starą wersję korzystającą z analizy i nową wersję korzystającą z Firebase. Synchronizacje między dwiema bazami danych są obsługiwane przez Parse Cloud Code (Parse to Firebase), a Twój kod nasłuchuje zmian w Firebase i synchronizuje te zmiany z Parse. Zanim zaczniesz korzystać z nowej wersji, musisz:

  • Przekonwertuj istniejące dane analizy na nową strukturę Firebase i zapisz je w bazie danych czasu rzeczywistego Firebase.
  • Zapisuj funkcje Parse Cloud Code, które używają interfejsu Firebase REST API do zapisywania w Firebase Realtime Database zmian wprowadzonych w Parse Data przez starych klientów.
  • Napisz i wdróż kod, który nasłuchuje zmian w Firebase i synchronizuje je z bazą danych Parse.

Ten scenariusz zapewnia czyste oddzielenie starego i nowego kodu oraz zapewnia prostotę obsługi klientów. Wyzwania tego scenariusza dotyczą obsługi dużych zestawów danych podczas początkowego eksportu i zapewnienia, że ​​synchronizacja dwukierunkowa nie generuje nieskończonej rekursji.

Podwójny zapis

W tym scenariuszu piszesz nową wersję aplikacji, która używa zarówno Firebase, jak i Parse, używając Parse Cloud Code do synchronizowania zmian wprowadzonych przez starych klientów z analizy danych do bazy danych czasu rzeczywistego Firebase. Gdy wystarczająca liczba osób przeprowadzi migrację z wersji aplikacji tylko do analizowania, możesz usunąć kod analizy z wersji do podwójnego zapisu.

Ten scenariusz nie wymaga żadnego kodu po stronie serwera. Wadą jest to, że dane, do których nie ma dostępu, nie są migrowane, a rozmiar aplikacji jest zwiększany przez użycie obu pakietów SDK.

Uwierzytelnianie Firebase

Uwierzytelnianie Firebase może uwierzytelniać użytkowników przy użyciu haseł i popularnych dostawców tożsamości federacyjnych, takich jak Google, Facebook i Twitter. Udostępnia również biblioteki interfejsu użytkownika, które pozwalają zaoszczędzić znaczące inwestycje wymagane do wdrożenia i utrzymania pełnego środowiska uwierzytelniania dla aplikacji na wszystkich platformach.

Więcej informacji można znaleźć w dokumentach dotyczących uwierzytelniania Firebase .

Różnice w parse Auth

Parse zapewnia wyspecjalizowaną klasę użytkowników o nazwie PFUser która automatycznie obsługuje funkcje wymagane do zarządzania kontami użytkowników. PFUser jest podklasą PFObject , co oznacza, że ​​dane użytkownika są dostępne w Parse Data i mogą być rozszerzone o dodatkowe pola, jak każdy inny PFObject .

FIRUser ma ustalony zestaw podstawowych właściwości - unikalny identyfikator, podstawowy adres e-mail, imię i nazwisko oraz adres URL zdjęcia - przechowywanych w osobnej bazie danych użytkowników projektu; te właściwości mogą być aktualizowane przez użytkownika. Nie można bezpośrednio dodawać innych właściwości do obiektu FIRUser ; Zamiast tego możesz przechowywać dodatkowe właściwości w bazie danych czasu rzeczywistego Firebase.

Poniżej znajduje się przykład, w jaki sposób można zarejestrować użytkownika i dodać dodatkowe pole numeru telefonu.

Analizować
 PFUser *user = [PFUser user];
user.username = @"my name";
user.password = @"my pass";
user.email = @"email@example.com";

// other fields can be set just like with PFObject
user[@"phone"] = @"415-392-0202";

[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
  if (!error) {
    // Hooray! Let them use the app now.
  } else {
    // Something went wrong
    NSString *errorString = [error userInfo][@"error"];
  }
}];
 
Firebase
 [[FIRAuth auth] createUserWithEmail:@"email@example.com"
                           password:@"my pass"
                         completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
  if (!error) {
    FIRDatabaseReference *ref = [[FIRDatabase database] reference];
    [[[[ref child:@"users"] child:user.uid] child:@"phone"] setValue:@"415-392-0202"
  } else {
    // Something went wrong
    NSString *errorString = [error userInfo][@"error"];
  }
}];
 

Sugerowana strategia migracji

Migrate Accounts

Aby przenieść konta użytkowników z Parse do Firebase, wyeksportuj bazę danych użytkowników do pliku JSON lub CSV, a następnie zaimportuj plik do projektu Firebase za pomocą polecenia auth:import w interfejsie wiersza polecenia auth:import .

Najpierw wyeksportuj bazę danych użytkowników z konsoli analizy lub własnej hostowanej bazy danych. Na przykład plik JSON wyeksportowany z konsoli Parse może wyglądać następująco:

{ // Username/password user
  "bcryptPassword": "$2a$10$OBp2hxB7TaYZgKyTiY48luawlTuYAU6BqzxJfpHoJMdZmjaF4HFh6",
  "email": "user@example.com",
  "username": "testuser",
  "objectId": "abcde1234",
  ...
},
{ // Facebook user
  "authData": {
    "facebook": {
      "access_token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
      "expiration_date": "2017-01-02T03:04:05.006Z",
      "id": "1000000000"
    }
  },
  "username": "wXyZ987654321StUv",
  "objectId": "fghij5678",
  ...
}

Następnie przekształć wyeksportowany plik do formatu wymaganego przez interfejs wiersza polecenia Firebase. Użyj objectId swoich użytkowników Parse jako localId użytkowników Firebase. Ponadto base64 koduje wartości bcryptPassword z Parse i używa ich w polu passwordHash . Na przykład:

{
  "users": [
    {
      "localId": "abcde1234",  // Parse objectId
      "email": "user@example.com",
      "displayName": "testuser",
      "passwordHash": "JDJhJDEwJE9CcDJoeEI3VGFZWmdLeVRpWTQ4bHVhd2xUdVlBVTZCcXp4SmZwSG9KTWRabWphRjRIRmg2",
    },
    {
      "localId": "fghij5678",  // Parse objectId
      "displayName": "wXyZ987654321StUv",
      "providerUserInfo": [
        {
          "providerId": "facebook.com",
          "rawId": "1000000000",  // Facebook ID
        }
      ]
    }
  ]
}

Na koniec zaimportuj przekształcony plik za pomocą interfejsu wiersza polecenia Firebase, określając bcrypt jako algorytm wyznaczania wartości skrótu:

firebase auth:import account_file.json --hash-algo=BCRYPT

Migracja danych użytkownika

Jeśli przechowujesz dodatkowe dane swoich użytkowników, możesz przenieść je do Bazy danych czasu rzeczywistego Firebase, korzystając ze strategii opisanych w sekcji migracji danych . Jeśli przenosisz konta za pomocą procesu opisanego w sekcji migracji kont , Twoje konta Firebase mają takie same identyfikatory jak kont Parse, co pozwala na łatwą migrację i odtworzenie wszelkich relacji określonych przez identyfikator użytkownika.

Komunikacja w chmurze Firebase

Firebase Cloud Messaging (FCM) to wieloplatformowe rozwiązanie do przesyłania wiadomości, które pozwala niezawodnie dostarczać wiadomości i powiadomienia bez żadnych kosztów. Kompozytor powiadomień to bezpłatna usługa oparta na Firebase Cloud Messaging, która umożliwia kierowanie powiadomień użytkowników dla twórców aplikacji mobilnych.

Zobacz dokumentację Firebase Cloud Messaging, aby dowiedzieć się więcej.

Różnice w przypadku powiadomień push analizy

Każda aplikacja Parse zainstalowana na urządzeniu zarejestrowanym na potrzeby powiadomień ma powiązany obiekt Installation , w którym przechowywane są wszystkie dane potrzebne do kierowania powiadomień. Installation jest podklasą PFUser , co oznacza, że ​​możesz dodać dowolne dodatkowe dane do swoich instancji Installation .

Kompozytor powiadomień zapewnia predefiniowane segmenty użytkowników na podstawie informacji, takich jak aplikacja, wersja aplikacji i język urządzenia. Możesz tworzyć bardziej złożone segmenty użytkowników, korzystając ze zdarzeń i usług Google Analytics do tworzenia list odbiorców. Więcej informacji znajdziesz w przewodniku pomocniczym dotyczącym odbiorców . Te informacje dotyczące kierowania nie są widoczne w bazie danych czasu rzeczywistego Firebase.

Sugerowana strategia migracji

Migracja tokenów urządzeń

Podczas gdy Parse używa tokenów urządzeń APN do docelowych instalacji dla powiadomień, FCM używa tokenów rejestracji FCM zmapowanych na tokeny urządzeń APN. Po prostu dodaj FCM SDK do swojej aplikacji na iOS, a ona automatycznie pobierze token FCM .

Migracja kanałów do tematów FCM

Jeśli używasz kanałów analizy do wysyłania powiadomień, możesz przeprowadzić migrację do tematów FCM, które zapewniają ten sam model wydawca-subskrybent. Aby obsłużyć przejście z analizy do FCM, możesz napisać nową wersję aplikacji, która korzysta z zestawu Parse SDK, aby anulować subskrypcję kanałów analizy, oraz zestawu FCM SDK, aby zasubskrybować odpowiednie tematy FCM.

Na przykład, jeśli Twój użytkownik zasubskrybował temat „Giants”, możesz zrobić coś takiego:

 PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation removeObject:@"Giants" forKey:@"channels"];
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
  if (succedeed) {
    [[FIRMessaging messaging] subscribeToTopic:@"/topics/Giants"];
  } else {
    // Something went wrong unsubscribing
  }
}];
 

Korzystając z tej strategii, możesz wysyłać wiadomości zarówno do kanału analizy, jak i odpowiedniego tematu FCM, obsługując użytkowników zarówno starej, jak i nowej wersji. Gdy wystarczająca liczba użytkowników przeprowadzi migrację z wersji aplikacji tylko do analizowania, możesz wyłączyć tę wersję i rozpocząć wysyłanie tylko przy użyciu FCM.

Więcej informacji znajdziesz w dokumentacji tematów FCM .

Zdalna konfiguracja Firebase

Firebase Remote Config to usługa w chmurze, która umożliwia zmianę działania i wyglądu aplikacji bez konieczności pobierania przez użytkowników aktualizacji aplikacji. Korzystając ze Zdalnej konfiguracji, tworzysz domyślne wartości w aplikacji, które kontrolują zachowanie i wygląd aplikacji. Następnie możesz później użyć konsoli Firebase do zastąpienia domyślnych wartości w aplikacji dla wszystkich użytkowników aplikacji lub dla segmentów Twojej bazy użytkowników.

Zdalna konfiguracja Firebase może być bardzo przydatna podczas migracji w przypadkach, gdy chcesz przetestować różne rozwiązania i mieć możliwość dynamicznego przenoszenia większej liczby klientów do innego dostawcy. Na przykład, jeśli masz wersję aplikacji, która używa zarówno Firebase, jak i Parse do danych, możesz użyć reguły losowego percentyla, aby określić, którzy klienci czytają z Firebase, i stopniowo zwiększać procent.

Aby dowiedzieć się więcej o zdalnej konfiguracji Firebase, zobacz wprowadzenie do Zdalnej konfiguracji .

Różnice z parse Config

Za pomocą opcji Parse config można dodawać pary klucz / wartość do aplikacji na PFConfig , a następnie pobrać PFConfig na kliencie. Każda PFConfig instancja PFConfig jest zawsze niezmienna. Kiedy w przyszłości pobierzesz nową PFConfig z sieci, nie zmodyfikuje ona żadnej istniejącej instancji PFConfig , ale utworzy nową i udostępni ją za pośrednictwem currentConfig .

Dzięki zdalnej konfiguracji Firebase tworzysz w aplikacji wartości domyślne dla par klucz / wartość, które możesz zastąpić w konsoli Firebase, a także możesz używać reguł i warunków, aby zapewnić różne wrażenia użytkownika aplikacji w różnych segmentach bazy użytkowników. Zdalna konfiguracja Firebase implementuje klasę pojedynczą, która udostępnia pary klucz / wartość dla Twojej aplikacji. Początkowo singleton zwraca wartości domyślne zdefiniowane w aplikacji. Możesz pobrać nowy zestaw wartości z serwera w dowolnym momencie dogodnym dla Twojej aplikacji; po pomyślnym pobraniu nowego zestawu możesz wybrać, kiedy go aktywować, aby nowe wartości były dostępne dla aplikacji.

Sugerowana strategia migracji

Możesz przejść do Firebase Remote Config, kopiując pary klucz / wartość konfiguracji Parse do konsoli Firebase, a następnie wdrażając nową wersję aplikacji korzystającej z Firebase Remote Config.

Jeśli chcesz poeksperymentować zarówno z analizowaniem konfiguracji, jak i zdalną konfiguracją Firebase, możesz wdrożyć nową wersję aplikacji, która korzysta z obu pakietów SDK, do czasu migracji wystarczającej liczby użytkowników z wersji Tylko do analizy.

Porównanie kodów

Analizować

 [PFConfig getConfigInBackgroundWithBlock:^(PFConfig *config, NSError *error) {
  if (!error) {
    NSLog(@"Yay! Config was fetched from the server.");
  } else {
    NSLog(@"Failed to fetch. Using Cached Config.");
    config = [PFConfig currentConfig];
  }

  NSString *welcomeMessage = config[@"welcomeMessage"];
  if (!welcomeMessage) {
    NSLog(@"Falling back to default message.");
    welcomeMessage = @"Welcome!";
  }
}];
 

Firebase

 FIRRemoteConfig remoteConfig = [FIRRemoteConfig remoteConfig];
// Set defaults from a plist file
[remoteConfig setDefaultsFromPlistFileName:@"RemoteConfigDefaults"];

[remoteConfig fetchWithCompletionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) {
  if (status == FIRRemoteConfigFetchStatusSuccess) {
    NSLog(@"Yay! Config was fetched from the server.");
    // Once the config is successfully fetched it must be activated before newly fetched
    // values are returned.
    [self.remoteConfig activateFetched];
  } else {
    NSLog(@"Failed to fetch. Using last fetched or default.");
  }
}];

// ...

// When this is called, the value of the latest fetched and activated config is returned;
// if there's none, the default value is returned.
NSString welcomeMessage = remoteConfig[@"welcomeMessage"].stringValue;