Google is committed to advancing racial equity for Black communities. See how.
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Migra la tua app Parse per iOS su Firebase

Se sei un utente Parse alla ricerca di una soluzione alternativa di back-end come servizio, Firebase potrebbe essere la scelta ideale per la tua app iOS.

Questa guida descrive come integrare servizi specifici nella tua app. Per istruzioni di base sulla configurazione di Firebase, consultare la Guida all'installazione di iOS .

statistiche di Google

Google Analytics è una soluzione di misurazione delle app gratuita che fornisce informazioni sull'utilizzo delle app e il coinvolgimento degli utenti. Analytics si integra tra le funzionalità di Firebase e offre rapporti illimitati per un massimo di 500 eventi distinti che è possibile definire utilizzando Firebase SDK.

Consulta i documenti di Google Analytics per saperne di più.

Strategia di migrazione suggerita

L'uso di diversi fornitori di analisi è uno scenario comune che si applica facilmente a Google Analytics. Aggiungilo alla tua app per beneficiare degli eventi e delle proprietà dell'utente che Analytics raccoglie automaticamente, come prima apertura, aggiornamento dell'app, modello del dispositivo, età.

Per eventi personalizzati e proprietà dell'utente, è possibile utilizzare una doppia strategia di scrittura utilizzando sia Parse Analytics che Google Analytics per registrare eventi e proprietà, che consente di implementare gradualmente la nuova soluzione.

Confronto del codice

Analisi di 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];
 

statistiche di Google

 // 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 su cloud NoSQL. I dati vengono archiviati come JSON e sincronizzati in tempo reale su ogni client connesso.

Consulta i documenti del database in tempo reale di Firebase per ulteriori informazioni.

Differenze con dati di analisi

Oggetti

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

Tutti i dati del database in tempo reale di Firebase sono archiviati come oggetti JSON e non esiste un equivalente per PFObject ; scrivi semplicemente all'albero JSON valori di tipi che corrispondono ai tipi JSON disponibili.

Di seguito è riportato un esempio di come è possibile salvare i punteggi più alti per una partita.

Parse
 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 maggiori dettagli, consulta la guida alla lettura e alla scrittura dei dati su iOS .

Relazioni tra i dati

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

Nel database in tempo reale di Firebase, le relazioni sono meglio espresse utilizzando strutture di dati semplici che dividono i dati in percorsi separati, in modo che possano essere scaricati in modo efficiente in chiamate separate.

Di seguito è riportato un esempio di come è possibile strutturare la relazione tra i post in un'app di blog e i loro autori.

Parse
 // 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 seguente layout di dati è il risultato.

{
  // 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, consultare la guida Struttura del database .

Lettura dei dati

In Parse leggi i dati utilizzando l'ID di un oggetto Parse specifico o eseguendo query utilizzando PFQuery .

In Firebase, i dati vengono recuperati collegando un listener asincrono a un riferimento al database. Il listener viene attivato una volta per lo stato iniziale dei dati e di nuovo quando i dati cambiano, quindi non sarà necessario aggiungere alcun codice per determinare se i dati sono cambiati.

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

Parse
 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 ulteriori dettagli sui tipi disponibili di listener di eventi e su come ordinare e filtrare i dati, consultare la guida di lettura e scrittura dei dati su iOS .

Strategia di migrazione suggerita

Ripensare i tuoi dati

Firebase Realtime Database è ottimizzato per sincronizzare i dati in millisecondi su tutti i client connessi e la struttura dei dati risultante è diversa dai dati core Parse. Ciò significa che il primo passo della migrazione è considerare le modifiche richieste dai dati, tra cui:

  • Come devono essere mappati i tuoi oggetti Parse sui dati di Firebase
  • Se hai relazioni genitore-figlio, come suddividere i tuoi dati su percorsi diversi in modo che possano essere scaricati in modo efficiente in chiamate separate.

Migra i tuoi dati

Dopo aver deciso come strutturare i dati in Firebase, è necessario pianificare come gestire il periodo durante il quale l'app deve scrivere in entrambi i database. Le tue scelte sono:

Sincronizzazione in background

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

  • Converti i tuoi dati di analisi esistenti nella nuova struttura di Firebase e scrivili nel database in tempo reale di Firebase.
  • Scrivere le funzioni del codice cloud di analisi che utilizzano l'API REST di Firebase per scrivere nel database in tempo reale di Firebase le modifiche apportate nei dati di analisi dai vecchi client.
  • Scrivi e distribuisci il codice che ascolta le modifiche su Firebase e le sincronizza con il database Parse.

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

Doppia scrittura

In questo scenario, scrivi una nuova versione dell'app che utilizza sia Firebase che Parse, utilizzando Parse Cloud Code per sincronizzare le modifiche apportate dai vecchi client dai dati di analisi al database in tempo reale di Firebase. Quando un numero sufficiente di persone è migrato dalla versione di solo analisi dell'app, è possibile rimuovere il codice di analisi dalla versione doppia scrittura.

Questo scenario non richiede alcun codice lato server. Gli svantaggi sono che i dati a cui non si accede non vengono migrati e che la dimensione della tua app viene aumentata dall'uso di entrambi gli SDK.

Autenticazione Firebase

Firebase Authentication può autenticare gli utenti utilizzando password e provider di identità federati popolari come Google, Facebook e Twitter. Fornisce inoltre librerie dell'interfaccia utente per risparmiare gli investimenti significativi richiesti per implementare e mantenere un'esperienza di autenticazione completa per la tua app su tutte le piattaforme.

Consulta i documenti di autenticazione Firebase per ulteriori informazioni.

Differenze con Parse Auth

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

Un FIRUser ha una serie fissa di proprietà di base - un ID univoco, un indirizzo e-mail primario, un nome e un URL di foto - memorizzati in un database utente di un progetto separato; tali proprietà possono essere aggiornate dall'utente. Non è possibile aggiungere direttamente altre proprietà all'oggetto FIRUser ; invece, è possibile memorizzare le proprietà aggiuntive nel database in tempo reale di Firebase.

Di seguito è riportato un esempio di come è possibile iscriversi a un utente e aggiungere un campo di numero di telefono aggiuntivo.

Parse
 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

Migrare gli account

Per migrare gli account utente da Parse a Firebase, esportare il database utente in un file JSON o CSV, quindi importare il file nel progetto Firebase utilizzando il comando auth:import della CLI di Firebase.

Innanzitutto, esporta il tuo database utente dalla console Parse o dal database self-hosted. Ad esempio, un file JSON esportato dalla console di Parse potrebbe essere simile al seguente:

{ // 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 dalla CLI di Firebase. Usa l' objectId dei tuoi utenti Parse come localId dei tuoi utenti Firebase. Inoltre, base64 codifica i valori di bcryptPassword da Parse e li utilizza nel campo passwordHash . Per 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 della riga di comando di Firebase, specificando bcrypt come algoritmo hash:

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

Migrare i dati utente

Se si memorizzano dati aggiuntivi per i propri utenti, è possibile migrarli nel database in tempo reale di Firebase 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 hanno gli stessi ID dei tuoi account Parse, consentendoti di migrare e riprodurre facilmente qualsiasi relazione codificata dall'ID utente.

Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) è una soluzione di messaggistica multipiattaforma che consente di recapitare in modo affidabile messaggi e notifiche gratuitamente. Il compositore di Notifiche è un servizio gratuito basato su Firebase Cloud Messaging che consente notifiche utente mirate per gli sviluppatori di app mobili.

Consulta i documenti di Firebase Cloud Messaging per saperne di più.

Differenze con le notifiche push di analisi

Ogni applicazione Parse installata su un dispositivo registrato per le notifiche ha un oggetto Installation associato, in cui vengono archiviati tutti i dati necessari per indirizzare le notifiche. Installation è una sottoclasse di PFUser , il che significa che è possibile aggiungere eventuali dati aggiuntivi alle istanze di Installation .

Il compositore di Notifiche fornisce segmenti di utenti predefiniti in base a informazioni come app, versione dell'app e lingua del dispositivo. Puoi creare segmenti di utenti più complessi utilizzando eventi e proprietà di Google Analytics per creare segmenti di pubblico. Consulta la guida di aiuto del pubblico per saperne di più. Queste informazioni di targeting non sono visibili nel database in tempo reale di Firebase.

Strategia di migrazione suggerita

Migrazione di token dispositivo

Mentre Parse utilizza i token del dispositivo APN per indirizzare le installazioni alle notifiche, FCM utilizza i token di registrazione FCM associati ai token del dispositivo APN. Basta aggiungere l'SDK FCM alla tua app iOS per recuperare automaticamente un token FCM .

Migrazione dei canali agli argomenti FCM

Se si utilizzano i canali Parse per inviare notifiche, è possibile migrare agli argomenti FCM, che forniscono lo stesso modello editore-abbonato. Per gestire la transizione da Parse a FCM, è possibile scrivere una nuova versione dell'app che utilizza Parse SDK per annullare l'iscrizione ai canali Parse e FCM SDK per iscriversi agli argomenti FCM corrispondenti.

Ad esempio, se il tuo utente è iscritto all'argomento "Giganti", faresti qualcosa del tipo:

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

Utilizzando questa strategia, è possibile inviare messaggi sia al canale Parse sia all'argomento FCM corrispondente, supportando gli utenti di versioni sia vecchie che nuove. Quando un numero sufficiente di utenti è migrato dalla versione solo analisi dell'app, è possibile annullare il tramonto di quella versione e iniziare a inviare utilizzando solo FCM.

Consulta i documenti degli argomenti FCM per saperne di più.

Firebase Remote Config

Firebase Remote Config è un servizio cloud che consente di modificare il comportamento e l'aspetto dell'app senza richiedere agli utenti di scaricare un aggiornamento dell'app. Quando si utilizza la configurazione remota, si creano valori predefiniti in-app che controllano il comportamento e l'aspetto dell'app. Quindi, in seguito puoi utilizzare la console di Firebase per sovrascrivere i valori predefiniti in-app per tutti gli utenti dell'app o per i segmenti della tua base utenti.

Firebase Remote Config può essere molto utile durante le migrazioni nei casi in cui si desidera testare soluzioni diverse ed essere in grado di spostare dinamicamente più client su un altro provider. Ad esempio, se si dispone di una versione dell'app che utilizza sia Firebase che Parse per i dati, è possibile utilizzare una regola di percentile casuale per determinare quali client leggono da Firebase e aumentare gradualmente la percentuale.

Per ulteriori informazioni su Firebase Remote Config, consultare l' introduzione di Remote Config .

Differenze con Parse Config

Con Parse config è possibile aggiungere coppie chiave / valore all'app nella Dashboard di Parse Config, quindi recuperare PFConfig sul client. Ogni istanza di PFConfig che ottieni è sempre immutabile. Quando in futuro recupererai un nuovo PFConfig dalla rete, non modificherà alcuna istanza PFConfig esistente, ma ne creerà una nuova e la renderà disponibile tramite currentConfig .

Con Firebase Remote Config crei impostazioni predefinite in-app per coppie chiave / valore che puoi ignorare dalla console di Firebase e puoi utilizzare regole e condizioni per fornire variazioni sull'esperienza utente della tua app a diversi segmenti della tua base utenti. Firebase Remote Config implementa una classe singleton che rende le coppie chiave / valore disponibili per la tua app. Inizialmente il singleton restituisce i valori predefiniti definiti in-app. Puoi recuperare un nuovo set di valori dal server in qualsiasi momento comodo per la tua app; dopo che il nuovo set è stato recuperato correttamente, puoi scegliere quando attivarlo per rendere disponibili i nuovi valori all'app.

Strategia di migrazione suggerita

Puoi passare a Firebase Remote Config copiando le coppie chiave / valore della tua configurazione Parse sulla console di Firebase, quindi distribuendo una nuova versione dell'app che utilizza Firebase Remote Config.

Se si desidera sperimentare sia Parse Config che Firebase Remote Config, è possibile distribuire una nuova versione dell'app che utilizza entrambi gli SDK fino a quando un numero sufficiente di utenti è migrato dalla versione solo Parse.

Confronto del codice

Parse

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