Parse iOS Uygulamanızı Firebase'e taşıyın

Hizmet olarak alternatif bir Arka Uç çözümü arayan bir Ayrıştırma kullanıcısıysanız, iOS uygulamanız için Firebase ideal seçim olabilir.

Bu kılavuz, belirli hizmetleri uygulamanıza nasıl entegre edeceğinizi açıklar. Temel Firebase kurulum talimatları için iOS+ Kurulum kılavuzuna bakın.

Google Analytics

Google Analytics, uygulama kullanımı ve kullanıcı etkileşimi hakkında bilgi sağlayan ücretsiz bir uygulama ölçüm çözümüdür. Analytics, Firebase özellikleri arasında entegre olur ve size Firebase SDK'sını kullanarak tanımlayabileceğiniz 500'e kadar farklı olay için sınırsız raporlama sağlar.

Daha fazla bilgi edinmek için Google Analytics belgelerine bakın.

Önerilen Taşıma Stratejisi

Farklı analiz sağlayıcılarının kullanılması, Google Analytics'e kolayca uygulanabilen yaygın bir senaryodur. İlk açılış, uygulama güncellemesi, cihaz modeli, yaş gibi Analytics'in otomatik olarak topladığı etkinliklerden ve kullanıcı özelliklerinden yararlanmak için uygulamanıza eklemeniz yeterlidir.

Özel etkinlikler ve kullanıcı mülkleri için, olayları ve mülkleri günlüğe kaydetmek için hem Parse Analytics'i hem de Google Analytics'i kullanarak yeni çözümü kademeli olarak kullanıma sunmanıza olanak tanıyan bir çift yazma stratejisi kullanabilirsiniz.

Kod Karşılaştırma

Analizleri Ayrıştırma

// 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 Gerçek Zamanlı Veritabanı

Firebase Realtime Database, NoSQL bulutta barındırılan bir veritabanıdır. Veriler JSON olarak depolanır ve bağlı her istemciyle gerçek zamanlı olarak senkronize edilir.

Daha fazla bilgi için Firebase Realtime Database belgelerine bakın.

Ayrıştırma Verileri ile Farklılıklar

nesneler

Ayrıştırma'da, JSON uyumlu verilerin anahtar/değer çiftlerini içeren bir PFObject veya bunun bir alt sınıfını depolarsınız. Veriler şemasızdır, yani her PFObject üzerinde hangi anahtarların bulunduğunu belirtmeniz gerekmez.

Tüm Firebase Realtime Database verileri JSON nesneleri olarak depolanır ve PFObject için eşdeğeri yoktur; mevcut JSON türlerine karşılık gelen türlerin değerlerini JSON ağacına yazmanız yeterlidir.

Aşağıda, bir oyun için yüksek puanları nasıl kaydedebileceğinize dair bir örnek verilmiştir.

Ayrıştırma
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
  }
}];
Daha fazla ayrıntı için Apple platformlarında Veri Okuma ve Yazma kılavuzuna bakın.

Veriler Arasındaki İlişkiler

Bir PFObject başka bir PFObject ile ilişkisi olabilir: herhangi bir nesne, diğer nesneleri değerler olarak kullanabilir.

Firebase Realtime Database'de ilişkiler, verileri ayrı yollara bölen düz veri yapıları kullanılarak daha iyi ifade edilir, böylece ayrı çağrılarda verimli bir şekilde indirilebilirler.

Aşağıda, bir blog uygulamasındaki gönderiler ile yazarları arasındaki ilişkiyi nasıl yapılandırabileceğinizin bir örneği verilmiştir.

Ayrıştırma
// 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]

Aşağıdaki veri düzeni sonucudur.

{
  // 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"
    }
    ...
  }
}
Daha fazla ayrıntı için Veritabanınızı Yapın kılavuzuna bakın.

Veri Okuma

Ayrıştırma'da, belirli bir Ayrıştırma nesnesinin kimliğini kullanarak veya PFQuery kullanarak sorguları yürüterek verileri okursunuz.

Firebase'de, bir veritabanı referansına eşzamansız bir dinleyici ekleyerek verileri alırsınız. Dinleyici, verilerin ilk durumu için bir kez ve veriler değiştiğinde yeniden tetiklenir, bu nedenle verilerin değişip değişmediğini belirlemek için herhangi bir kod eklemeniz gerekmez.

Aşağıda, "Nesneler" bölümünde sunulan örneğe dayalı olarak belirli bir oyuncu için puanları nasıl alabileceğinizin bir örneği verilmiştir.

Ayrıştırma
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);
}];
Kullanılabilir olay dinleyici türleri ve verilerin nasıl sıralanacağı ve filtreleneceği hakkında daha fazla ayrıntı için Apple platformlarında Veri Okuma ve Yazma kılavuzuna bakın.

Önerilen Taşıma Stratejisi

Verilerinizi Yeniden Düşünün

Firebase Gerçek Zamanlı Veritabanı, bağlı tüm istemciler arasında milisaniye cinsinden verileri senkronize etmek için optimize edilmiştir ve elde edilen veri yapısı, Temel Ayrıştırma verisinden farklıdır. Bu, geçişinizin ilk adımının, aşağıdakiler dahil olmak üzere, verilerinizin hangi değişiklikleri gerektirdiğini düşünmek olduğu anlamına gelir:

  • Ayrıştırma nesneleriniz Firebase verileriyle nasıl eşleşmelidir?
  • Ebeveyn-çocuk ilişkileriniz varsa, farklı aramalarda verimli bir şekilde indirilebilmesi için verilerinizi farklı yollara nasıl bölebilirsiniz.

Verilerinizi Taşıyın

Firebase'de verilerinizi nasıl yapılandıracağınıza karar verdikten sonra, uygulamanızın her iki veritabanına da yazması gereken süreyi nasıl ele alacağınızı planlamanız gerekir. Seçimleriniz:

Arka Plan Senkronizasyonu

Bu senaryoda, uygulamanın iki sürümü vardır: Ayrıştırma kullanan eski sürüm ve Firebase kullanan yeni sürüm. İki veritabanı arasındaki senkronizasyonlar, Parse Cloud Code (Parse to Firebase) tarafından gerçekleştirilir; kodunuz Firebase'deki değişiklikleri dinler ve bu değişiklikleri Parse ile senkronize eder. Yeni sürümü kullanmaya başlamadan önce şunları yapmalısınız:

  • Mevcut Ayrıştırma Verilerinizi yeni Firebase yapısına dönüştürün ve Firebase Realtime Database'e yazın.
  • Eski istemciler tarafından Ayrıştırma Verilerinde yapılan değişiklikleri Firebase Gerçek Zamanlı Veritabanına yazmak için Firebase REST API'sini kullanan Ayrıştırma Bulut Kodu Yazma işlevleri.
  • Firebase'deki değişiklikleri dinleyen ve bunları Ayrıştırma veritabanıyla eşitleyen kodu yazın ve dağıtın.

Bu senaryo, eski ve yeni kodun temiz bir şekilde ayrılmasını sağlar ve istemcileri basit tutar. Bu senaryonun zorlukları, ilk dışa aktarmada büyük veri kümelerini ele almak ve çift yönlü eşitlemenin sonsuz özyineleme oluşturmamasını sağlamaktır.

Çift Yazma

Bu senaryoda, eski istemciler tarafından Ayrıştırma Verilerinden Firebase Gerçek Zamanlı Veritabanına yapılan değişiklikleri eşitlemek için Ayrıştırma Bulut Kodunu kullanarak, hem Firebase hem de Ayrıştırma kullanan uygulamanın yeni bir sürümünü yazarsınız. Uygulamanın yalnızca Ayrıştırma sürümünden yeterli sayıda kişi taşındığında, Ayrıştırma kodunu çift yazma sürümünden kaldırabilirsiniz.

Bu senaryo herhangi bir sunucu tarafı kodu gerektirmez. Dezavantajları, erişilemeyen verilerin taşınmaması ve her iki SDK'nın kullanılmasıyla uygulamanızın boyutunun artmasıdır.

Firebase Kimlik Doğrulaması

Firebase Authentication, şifreleri ve Google, Facebook ve Twitter gibi popüler birleşik kimlik sağlayıcıları kullanarak kullanıcıların kimliğini doğrulayabilir. Ayrıca, uygulamanız için tüm platformlarda eksiksiz bir kimlik doğrulama deneyimi uygulamak ve sürdürmek için gereken önemli yatırımdan tasarruf etmeniz için kullanıcı arabirimi kitaplıkları sağlar.

Daha fazla bilgi için Firebase Authentication belgelerine bakın.

Ayrıştırma Yetkilendirmesiyle Farklılıklar

Ayrıştırma, kullanıcı hesabı yönetimi için gereken işlevselliği otomatik olarak işleyen PFUser adlı özel bir kullanıcı sınıfı sağlar. PFUser , PFObject bir alt sınıfıdır; bu, kullanıcı verilerinin Parse Data içinde mevcut olduğu ve diğer herhangi bir PFObject gibi ek alanlarla genişletilebileceği anlamına gelir.

Bir FIRUser kullanıcısı, ayrı bir projenin kullanıcı veritabanında depolanan sabit bir temel özelliklere (benzersiz bir kimlik, birincil e-posta adresi, ad ve fotoğraf URL'si) sahiptir; bu özellikler kullanıcı tarafından güncellenebilir. FIRUser nesnesine doğrudan başka özellikler ekleyemezsiniz; bunun yerine, ek özellikleri Firebase Gerçek Zamanlı Veritabanınızda saklayabilirsiniz.

Aşağıda, bir kullanıcıyı nasıl kaydettirebileceğinize ve ek bir telefon numarası alanı ekleyebileceğinize ilişkin bir örnek verilmiştir.

Ayrıştırma
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"];
  }
}];

Önerilen Taşıma Stratejisi

Hesapları Taşıma

Kullanıcı hesaplarını Parse'dan Firebase'e taşımak için, kullanıcı veritabanınızı bir JSON veya CSV dosyasına aktarın, ardından Firebase CLI'nin auth:import komutunu kullanarak dosyayı Firebase projenize aktarın.

İlk olarak, kullanıcı veritabanınızı Ayrıştırma konsolundan veya kendi kendine barındırılan veritabanınızdan dışa aktarın. Örneğin, Ayrıştırma konsolundan dışa aktarılan bir JSON dosyası aşağıdaki gibi görünebilir:

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

Ardından, dışa aktarılan dosyayı Firebase CLI'nin gerektirdiği biçime dönüştürün. Ayrıştırma kullanıcılarınızın localId objectId olarak kullanın. Ayrıca base64, bcryptPassword değerlerini kodlayın ve bunları passwordHash alanında kullanın. Örneğin:

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

Son olarak, karma algoritma olarak bcrypt belirterek, dönüştürülen dosyayı Firebase CLI ile içe aktarın:

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

Kullanıcı Verilerini Taşı

Kullanıcılarınız için ek veri depoluyorsanız, veri taşıma bölümünde açıklanan stratejileri kullanarak bunları Firebase Realtime Database'e taşıyabilirsiniz. Hesap taşıma bölümünde açıklanan akışı kullanarak hesapları taşırsanız, Firebase hesaplarınız Ayrıştırma hesaplarınızla aynı kimliklere sahiptir ve bu, kullanıcı kimliği tarafından anahtarlanan ilişkileri kolayca taşımanıza ve yeniden oluşturmanıza olanak tanır.

Firebase Bulut Mesajlaşma

Firebase Cloud Messaging (FCM), mesajları ve bildirimleri hiçbir ücret ödemeden güvenilir bir şekilde iletmenizi sağlayan platformlar arası bir mesajlaşma çözümüdür. Bildirim oluşturucu, mobil uygulama geliştiricileri için hedeflenen kullanıcı bildirimlerini etkinleştiren, Firebase Bulut Mesajlaşma üzerine kurulmuş ücretsiz bir hizmettir.

Daha fazla bilgi edinmek için Firebase Bulut Mesajlaşma belgelerine bakın.

Ayrıştırma Push Bildirimleri ile Farklılıklar

Bildirimler için kayıtlı bir cihaza yüklenen her Ayrıştırma uygulamasının, bildirimleri hedeflemek için gereken tüm verileri depoladığınız ilişkili bir Installation nesnesi vardır. Installation , PFUser bir alt sınıfıdır; bu, Installation örneklerinize istediğiniz herhangi bir ek veriyi ekleyebileceğiniz anlamına gelir.

Bildirim oluşturucu, uygulama, uygulama sürümü ve cihaz dili gibi bilgilere dayalı olarak önceden tanımlanmış kullanıcı segmentleri sağlar. Kitle oluşturmak için Google Analytics etkinliklerini ve özelliklerini kullanarak daha karmaşık kullanıcı segmentleri oluşturabilirsiniz. Daha fazla bilgi edinmek için kitle yardım kılavuzuna bakın. Bu hedefleme bilgileri, Firebase Gerçek Zamanlı Veritabanında görünmez.

Önerilen Taşıma Stratejisi

Cihaz Simgelerini Taşıma

Ayrıştırma, bildirimler için yüklemeleri hedeflemek için APNs cihaz belirteçlerini kullanırken, FCM, APNs cihaz belirteçleriyle eşlenen FCM kayıt belirteçlerini kullanır. FCM SDK'yı Apple uygulamanıza eklemeniz yeterlidir, otomatik olarak bir FCM belirteci alacaktır.

Kanalları FCM Konularına Taşıma

Bildirimleri göndermek için ayrıştırma kanallarını kullanıyorsanız, aynı yayıncı-abone modelini sağlayan FCM konularına geçiş yapabilirsiniz. Ayrıştırmadan FCM'ye geçişi halletmek için, Ayrıştırma kanallarından çıkmak için Ayrıştırma SDK'sını ve ilgili FCM konularına abone olmak için FCM SDK'sını kullanan uygulamanın yeni bir sürümünü yazabilirsiniz.

Örneğin, kullanıcınız "Devler" konusuna aboneyse, şöyle bir şey yaparsınız:

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

Bu stratejiyi kullanarak, hem eski hem de yeni sürümlerin kullanıcılarını destekleyerek hem Ayrıştırma kanalına hem de ilgili FCM konusuna mesaj gönderebilirsiniz. Uygulamanın Yalnızca Ayrıştırma sürümünden yeterli sayıda kullanıcı geçiş yaptığında, bu sürümü kapatabilir ve yalnızca FCM kullanarak göndermeye başlayabilirsiniz.

Daha fazla bilgi edinmek için FCM konu belgelerine bakın.

Firebase Uzaktan Yapılandırma

Firebase Remote Config, kullanıcıların bir uygulama güncellemesi indirmesine gerek kalmadan uygulamanızın davranışını ve görünümünü değiştirmenize olanak tanıyan bir bulut hizmetidir. Remote Config'i kullanırken, uygulamanızın davranışını ve görünümünü kontrol eden uygulama içi varsayılan değerler oluşturursunuz. Ardından, tüm uygulama kullanıcıları veya kullanıcı tabanınızın segmentleri için uygulama içi varsayılan değerleri geçersiz kılmak için daha sonra Firebase konsolunu kullanabilirsiniz.

Firebase Remote Config, farklı çözümleri test etmek ve daha fazla istemciyi dinamik olarak farklı bir sağlayıcıya kaydırmak istediğiniz durumlarda geçişleriniz sırasında çok yararlı olabilir. Örneğin, uygulamanızın veriler için hem Firebase hem de Parse kullanan bir sürümü varsa, hangi istemcilerin Firebase'den okuduğunu belirlemek için rastgele bir yüzdelik dilim kuralı kullanabilir ve yüzdeyi kademeli olarak artırabilirsiniz.

Firebase Remote Config hakkında daha fazla bilgi edinmek için Remote Config tanıtımına bakın.

Ayrıştırma Yapılandırması ile Farklılıklar

Parse config ile, Parse Config Dashboard'da uygulamanıza anahtar/değer çiftleri ekleyebilir ve ardından istemcide PFConfig getirebilirsiniz. Aldığınız her PFConfig örneği her zaman değişmezdir. Gelecekte ağdan yeni bir PFConfig , mevcut herhangi bir PFConfig örneğini değiştirmez, bunun yerine yeni bir tane oluşturur ve bunu currentConfig aracılığıyla kullanılabilir hale getirir.

Firebase Remote Config ile, Firebase konsolundan geçersiz kılabileceğiniz anahtar/değer çiftleri için uygulama içi varsayılanlar oluşturursunuz ve kullanıcı tabanınızın farklı segmentlerine uygulamanızın kullanıcı deneyiminde varyasyonlar sağlamak için kurallar ve koşullar kullanabilirsiniz. Firebase Remote Config, anahtar/değer çiftlerini uygulamanız için kullanılabilir hale getiren bir singleton sınıfı uygular. Başlangıçta singleton, uygulama içinde tanımladığınız varsayılan değerleri döndürür. Uygulamanız için uygun olan herhangi bir zamanda sunucudan yeni bir değer kümesi getirebilirsiniz; yeni küme başarıyla getirildikten sonra, yeni değerleri uygulamada kullanılabilir hale getirmek için ne zaman etkinleştireceğinizi seçebilirsiniz.

Önerilen Taşıma Stratejisi

Parse yapılandırmanızın anahtar/değer çiftlerini Firebase konsoluna kopyalayarak ve ardından uygulamanın Firebase Remote Config kullanan yeni bir sürümünü dağıtarak Firebase Remote Config'e geçebilirsiniz.

Hem Parse Config hem de Firebase Remote Config ile deneme yapmak istiyorsanız, yalnızca Parse sürümünden yeterli sayıda kullanıcı geçiş yapana kadar uygulamanın her iki SDK'yı da kullanan yeni bir sürümünü dağıtabilirsiniz.

Kod Karşılaştırma

Ayrıştırma

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