Esegui la migrazione dell'app Parse per iOS a Firebase

Se sei un utente di Parse alla ricerca di un backend alternativo come di servizi, Firebase potrebbe essere la scelta ideale per la tua app per iOS.

Questa guida descrive come integrare servizi specifici nella tua app. Per istruzioni di base per la configurazione di Firebase, consulta Configurazione di iOS+ guida.

Google Analytics

Google Analytics è una soluzione di misurazione delle app gratuita che fornisce approfondimenti sull'utilizzo delle app e sul coinvolgimento degli utenti. Analytics si integra con le funzionalità di Firebase e fornisce report illimitati per un massimo di 500 eventi distinti che puoi definire utilizzando l'SDK Firebase.

Per scoprire di più, consulta la documentazione di Google Analytics.

Strategia di migrazione suggerita

L'utilizzo di provider di analisi diversi è uno scenario comune che si applica facilmente Google Analytics. Aggiungilo alla tua app per usufruire degli eventi e delle proprietà utente raccolti automaticamente daAnalytics, ad esempio prima apertura, aggiornamento dell'app, modello di dispositivo, età.

Per gli eventi personalizzati e le proprietà utente, puoi impiegare una strategia di scrittura doppia utilizzando analizzare Analytics e Google Analytics per registrare eventi e proprietà, il che consente di implementare gradualmente la nuova soluzione.

Confronto codice

Analizza analisi

// 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"
}];

Firebase Realtime Database

Firebase Realtime Database è un database ospitato nel cloud NoSQL. I dati vengono archiviati in formato JSON sincronizzati in tempo reale con ogni client connesso.

Per scoprire di più, consulta la documentazione di Firebase Realtime Database.

Differenze con l'analisi dei dati

Oggetti

In Parse memorizzi un PFObject, o una sua sottoclasse, che contiene coppie chiave-valore di dati compatibili con JSON. I dati sono senza schema, il che significa che non è necessario specificare quali chiavi esistono su ogni PFObject.

Tutti i dati di Firebase Realtime Database vengono archiviati come oggetti JSON e non esiste un equivalente per PFObject; è sufficiente scrivere nei valori dell'albero JSON dei tipi ai tipi JSON disponibili.

Di seguito è riportato un esempio di come potresti salvare i punteggi migliori per un gioco.

Analizza
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
  }
}];
Per ulteriori dettagli, consulta Guida alla lettura e alla scrittura di dati sulle piattaforme Apple.

Relazioni tra dati

Un PFObject può avere una relazione con un altro PFObject: qualsiasi oggetto può utilizzare altri oggetti come valori.

In Firebase Realtime Database, le relazioni sono espresse meglio utilizzando strutture di dati piatte che suddividono i dati in percorsi distinti, in modo che possano essere scaricati in modo efficiente in chiamate separate.

Di seguito è riportato un esempio di come puoi strutturare la relazione tra i post in una app di blogging e relativi autori.

Analizza
// 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]

Il risultato è il seguente layout di dati.

{
  // 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"
    }
    ...
  }
}
Per ulteriori dettagli, consulta Struttura il database guida.

Lettura dei dati

In Analizza, leggi i dati utilizzando l'ID di un oggetto Parse specifico oppure che esegue query utilizzando PFQuery.

In Firebase, i dati vengono recuperati collegando un ascoltatore asincrono a un riferimento di database. La il listener viene attivato una volta per lo stato iniziale dei dati e di nuovo quando i dati cambiano, In questo modo, non dovrai aggiungere alcun codice per determinare se i dati sono cambiati.

Di seguito è riportato un esempio di come puoi recuperare i punteggi di un determinato giocatore, in base a nell'esempio presentato nella sezione "Oggetti".

Analizza
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);
}];
Per maggiori dettagli sui tipi di listener di eventi disponibili e su come ordinare e filtrare i dati, controlla Lettura e scrittura di dati sulle piattaforme Apple guida.

Strategia di migrazione suggerita

Reinterpreta i tuoi dati

Firebase Realtime Database è ottimizzato per sincronizzare i dati in millisecondi tra tutti i dispositivi connessi e la struttura dei dati risultante è diversa dai dati principali di Parse. Ciò significa che Il primo passaggio della migrazione è valutare quali modifiche sono richieste dai dati, tra cui:

  • Come gli oggetti di analisi devono essere mappati ai dati Firebase
  • Se hai relazioni genitore-figlio, su come suddividere i dati su percorsi diversi in modo da può essere scaricato in modo efficiente in chiamate separate.

Esegui la migrazione dei tuoi dati

Dopo aver deciso come strutturare i dati in Firebase, devi pianificare come gestire il periodo durante il quale la tua app deve scrivere in entrambi i database. Le opzioni disponibili sono:

Sincronizzazione in background

In questo scenario, hai due versioni dell'app: quella precedente che utilizza l'analisi e una nuova che utilizza Firebase. Le sincronizzazioni tra i due database sono gestite da Parse Cloud Code (Parse a Firebase), con il codice che ascolta le modifiche su Firebase e le sincronizza con Parse. Prima di poter iniziare a utilizzare la nuova versione, devi:

  • Converti i dati di Parse esistenti nella nuova struttura Firebase e scrivili in Firebase Realtime Database.
  • Scrivere le funzioni Analizza Cloud Code che utilizzano l'API REST Firebase per scrivere Firebase Realtime Database modifiche apportate in Analizza dati da client precedenti.
  • Scrivi ed esegui il deployment del codice che rimane in ascolto delle modifiche su Firebase e le sincronizza con il Parse per configurare un database.

Questo scenario garantisce una separazione netta tra vecchio e nuovo codice e semplifica la gestione dei client. La Le sfide di questo scenario sono la gestione di grandi set di dati nell'esportazione iniziale e la garanzia che la sincronizzazione bidirezionale non genera una ricorsione infinita.

Scrittura doppia

In questo scenario, scriverai una nuova versione dell'app che utilizza sia Firebase che Parse, utilizzando Analizza Cloud Code per sincronizzare le modifiche apportate dai vecchi client dai dati di analisi Firebase Realtime Database. Quando un numero sufficiente di utenti ha eseguito la migrazione dalla versione dell'app solo Parse, puoi rimuovere il codice Parse dalla versione con doppia scrittura.

Questo scenario non richiede codice lato server. I suoi svantaggi sono che i dati che non sono non viene eseguita la migrazione dell'accesso e le dimensioni della tua app vengono aumentate dall'uso di entrambi gli SDK.

Firebase Authentication

Firebase Authentication può autenticare gli utenti utilizzando password e noti provider di identità federati come Google, Facebook e Twitter. Fornisce inoltre librerie UI per consentirti di risparmiare l'investimento necessario per implementare e mantenere un'esperienza di autenticazione completa per la tua app su su tutte le piattaforme.

Per scoprire di più, consulta la documentazione di Firebase Authentication.

Differenze rispetto all'autenticazione di analisi

Parse fornisce una classe utente specializzata chiamata PFUser che gestisce automaticamente la funzionalità richiesta per la gestione degli account utente. PFUser è una sottoclasse del PFObject, il che significa che i dati utente sono disponibili nell'analisi dei dati e possono essere estesi con campi aggiuntivi come qualsiasi altro PFObject.

Un FIRUser ha un insieme fisso di proprietà di base: un ID univoco, un indirizzo email principale un nome e l'URL di una foto, memorizzati in un database utente separato di un progetto possono essere aggiornate per l'utente. Non puoi aggiungere altre proprietà direttamente all'oggetto FIRUser, ma puoi archiviarle in Firebase Realtime Database.

Di seguito è riportato un esempio di come puoi registrare un utente e aggiungere un ulteriore campo per il numero di telefono.

Analizza
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"];
  }
}];

Strategia di migrazione suggerita

Esegui la migrazione degli account

Per eseguire la migrazione degli account utente da Parse a Firebase, esporta il database utenti in un file JSON o CSV, quindi importa il file nel progetto Firebase utilizzando auth:import dell'interfaccia a riga di comando di Firebase .

Innanzitutto, esporta il database utente dalla console Parse o dal database auto-in hosting. Ad esempio, un file JSON esportato dalla console di analisi potrebbe avere ad esempio:

{ // 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",
  ...
}

Quindi, trasforma il file esportato nel formato richiesto da Firebase nell'interfaccia a riga di comando. Utilizza objectId degli utenti di Parse come localId dei tuoi utenti Firebase. Inoltre, in base64 codificano bcryptPassword di valori di Analizza e usali nella sezione passwordHash . Ad esempio:

{
  "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
        }
      ]
    }
  ]
}

Infine, importa il file trasformato con l'interfaccia a riga di comando di Firebase, specificando bcrypt come algoritmo hash:

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

Esegui la migrazione dei dati utente

Se stai archiviando dati aggiuntivi per i tuoi utenti, puoi eseguirne la migrazione a Firebase Realtime Database utilizzando le strategie descritte nella sezione sulla migrazione dei dati. Se esegui la migrazione degli account utilizzando il flusso descritto nella sezione Migrazione degli account, i tuoi account Firebase avranno gli stessi ID dei tuoi account Parse, il che ti consente di eseguire facilmente la migrazione e riprodurre qualsiasi relazione basata sull'ID utente.

Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) è una soluzione di messaggistica multipiattaforma che ti consente di per consegnare messaggi e notifiche senza costi. Notifications Composer è un servizio senza costi su Firebase Cloud Messaging che attiva le notifiche utente target per gli sviluppatori di app mobile.

Per scoprire di più, consulta la documentazione di Firebase Cloud Messaging.

Differenze rispetto alle notifiche push di analisi

A ogni applicazione Parse installata su un dispositivo registrato per le notifiche è associata un'etichetta Installation, in cui archivi tutti i dati necessari per indirizzare le notifiche. Installation è una sottoclasse di PFUser, il che significa che puoi aggiungere eventuali dati aggiuntivi da trasferire alle istanze Installation.

Il generatore di notifiche fornisce segmenti di utenti predefiniti in base a informazioni quali app, versione dell'app e lingua del dispositivo. Puoi creare segmenti utenti più complessi utilizzando gli eventi e le proprietà Google Analytics per creare segmenti di pubblico. Visualizza i segmenti di pubblico guida di assistenza per saperne di più. Queste informazioni sul targeting non sono visibili in Firebase Realtime Database.

Strategia di migrazione suggerita

Migrazione dei token dispositivo

Anche se il comando Parse utilizza i token del dispositivo degli APN per scegliere come target le installazioni per le notifiche, FCM utilizza FCM token di registrazione mappato ai token del dispositivo degli APN. Devi solo aggiungere FCM SDK alla tua app Apple e recupererà automaticamente un token FCM.

Migrazione dei canali agli FCM Argomenti

Se usi Analizza canali per inviare notifiche, puoi eseguire la migrazione agli argomenti FCM, che forniscono lo stesso modello publisher-iscritto. Per gestire la transizione da Analizza a FCM, puoi scrivere una nuova versione dell'app che utilizza l'SDK Parse per annullare l'iscrizione ai canali Parse e l'SDK FCM per l'iscrizione FCM argomenti corrispondenti.

Ad esempio, se un utente è abbonato ai "Giants" argomento, ad esempio:

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

Utilizzando questa strategia, puoi inviare messaggi sia al canale di analisi che al canale FCM, che supporta gli utenti di versioni precedenti e nuove. Quando un numero sufficiente di utenti ha eseguito la migrazione Versione di sola analisi dell'app, puoi annullarla e iniziare a inviarla utilizzando solo FCM.

Consulta le FCM documenti relativi agli argomenti per saperne di più.

Firebase Remote Config

Firebase Remote Config è un servizio cloud che ti consente di modificare il comportamento e l'aspetto del tuo senza richiedere agli utenti di scaricare un aggiornamento. Quando usi Remote Config, crei immagini in-app valori predefiniti che controllano il comportamento e l'aspetto della tua app. Successivamente, potrai utilizzare Console Firebase per eseguire l'override dei valori predefiniti in-app per tutti gli utenti dell'app o per segmenti della tua base utenti.

Firebase Remote Config può essere molto utile durante le migrazioni se vuoi testare diverse soluzioni ed essere in grado di spostare dinamicamente più clienti su un altro provider. Ad esempio: Se disponi di una versione dell'app che utilizza sia Firebase che Parse per i dati, puoi utilizzare una con una regola di percentile casuale per determinare quali clienti leggono da Firebase e aumentare gradualmente la percentuale.

Per scoprire di più su Firebase Remote Config, consulta le Introduzione a Remote Config.

Differenze con l'analisi della configurazione

Con Parse Config puoi aggiungere coppie chiave/valore alla tua app nella dashboard Analizza configurazione, quindi Recupera PFConfig sul client. Ogni PFConfig istanza che get è sempre immutabile. Quando in futuro recupererai un nuovo PFConfig dalla rete, non verrà modificata alcuna istanza PFConfig esistente, ma ne verrà creata una nuova e resa disponibile tramite currentConfig.

Con Firebase Remote Config crei valori predefiniti in-app per coppie chiave/valore che puoi sostituire dalla console Firebase e puoi utilizzare regole e condizioni per fornire varianti dell'app l'esperienza utente ai diversi segmenti della base utenti. Firebase Remote Config implementa un singleton che rende le coppie chiave/valore disponibili per la tua app. Inizialmente il singleton torna i valori predefiniti da te definiti in-app. Puoi recuperare un nuovo insieme di valori dal server in qualsiasi momento conveniente per la tua app; Dopo che il nuovo set è stato recuperato, puoi scegliere quando attivarlo per rendere i nuovi valori disponibili per l'app.

Strategia di migrazione suggerita

Puoi passare a Firebase Remote Config copiando le coppie chiave/valore della configurazione di analisi alla console Firebase per poi eseguire il deployment di una nuova versione dell'app che usa Firebase Remote Config.

Se vuoi fare esperimenti sia con Parse Config sia con Firebase Remote Config, puoi eseguire il deployment di una nuova versione dell'app che utilizzi entrambi gli SDK finché un numero sufficiente di utenti non avrà eseguito la migrazione dalla versione solo Parse.

Confronto codice

Analizza

[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;