Catch up on everthing we announced at this year's Firebase Summit. Learn more

Apple platformlarında Veri Okuma ve Yazma

(İsteğe bağlı) Firebase Local Emulator Suite ile prototip oluşturun ve test edin

Uygulamanızın Realtime Database'den nasıl okuyup yazdığından bahsetmeden önce, Realtime Database işlevselliğini prototiplemek ve test etmek için kullanabileceğiniz bir dizi araç tanıtalım: Firebase Local Emulator Suite. Farklı veri modelleri deniyor, güvenlik kurallarınızı optimize ediyor veya arka uçla etkileşim kurmanın en uygun maliyetli yolunu bulmaya çalışıyorsanız, canlı hizmetleri dağıtmadan yerel olarak çalışabilmek harika bir fikir olabilir.

Gerçek Zamanlı Veritabanı öykünücüsü, uygulamanızın öykünülmüş veritabanı içeriğiniz ve yapılandırmanızın yanı sıra isteğe bağlı olarak öykünülmüş proje kaynaklarınızla (işlevler, diğer veritabanları ve güvenlik kuralları) etkileşim kurmasını sağlayan Yerel Öykünücü Paketi'nin bir parçasıdır.

Gerçek Zamanlı Veritabanı öykünücüsünü kullanmak yalnızca birkaç adımı içerir:

  1. Öykünücüye bağlanmak için uygulamanızın test yapılandırmasına bir kod satırı ekleme.
  2. Çalışan yerel proje dizininin kökü itibaren firebase emulators:start .
  3. Her zamanki gibi bir Realtime Database platformu SDK'sını veya Realtime Database REST API'sini kullanarak uygulamanızın prototip kodundan çağrı yapma.

Detaylı bir Gerçek Zamanlı Veritabanı ve Bulut İşlevleri içeren örneklerde mevcuttur. Ayrıca bir göz sahip olmalıdır Yerel Emülatörü Suite giriş .

Bir FIRDatabaseReference alın

Okuma veya yazma verileri veritabanından, sen bir örneğini ihtiyaç için FIRDatabaseReference :

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
var ref: DatabaseReference!

ref = Database.database().reference()

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
@property (strong, nonatomic) FIRDatabaseReference *ref;

self.ref = [[FIRDatabase database] reference];

Veri yaz

Bu belge, Firebase verilerini okuma ve yazmayla ilgili temel bilgileri kapsar.

Firebase veriler yazılır Database referansı ve referans bir asenkron dinleyici takılarak alınan. Dinleyici, verilerin ilk durumu için bir kez ve veriler değiştiğinde yeniden tetiklenir.

Temel yazma işlemleri

Temel yazma işlemleri için, kullanabileceğiniz setValue o yolda herhangi mevcut verileri değiştirerek, belirli bir referansa verileri kaydetmek. Bu yöntemi aşağıdakiler için kullanabilirsiniz:

  • Kullanılabilir JSON türlerine karşılık gelen türleri aşağıdaki gibi geçirin:
    • NSString
    • NSNumber
    • NSDictionary
    • NSArray

Örneğin, bir kullanıcı ekleyebilirsiniz setValue şöyle:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
self.ref.child("users").child(user.uid).setValue(["username": username])

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
[[[self.ref child:@"users"] child:authResult.user.uid]
    setValue:@{@"username": username}];

Kullanılması setValue bu şekilde tüm alt düğümler dahil belirtilen yerde verileri yazar. Ancak, tüm nesneyi yeniden yazmadan bir alt öğeyi güncelleyebilirsiniz. Kullanıcıların profillerini güncellemelerine izin vermek istiyorsanız, kullanıcı adını aşağıdaki gibi güncelleyebilirsiniz:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
self.ref.child("users/\(user.uid)/username").setValue(username)

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
[[[[_ref child:@"users"] child:user.uid] child:@"username"] setValue:username];

Verileri oku

Değer olaylarını dinleyerek verileri okuyun

Bir yolda verileri okumak ve değişiklikleri işler için kullanmak observeEventType:withBlock ait FIRDatabaseReference gözlemlemek için FIRDataEventTypeValue olayları.

Etkinlik tipi Tipik kullanım
FIRDataEventTypeValue Bir yolun tüm içeriğindeki değişiklikleri okuyun ve dinleyin.

Sen kullanabilirsiniz FIRDataEventTypeValue o olayın anda var olduğu, belirli bir yolda verileri okumak için olay. Bu yöntem, dinleyici eklendiğinde bir kez tetiklenir ve herhangi bir çocuk da dahil olmak üzere veriler her değiştiğinde tekrar tetiklenir. Olay geri arama bir geçirilir snapshot çocuk veriler dahil bu konumda tüm verileri içeren. Hiçbir veri yoksa, anlık dönecektir false Aradığınızda exists() ve nil onun okurken value özelliği.

Aşağıdaki örnek, veri tabanından bir gönderinin ayrıntılarını alan bir sosyal blog uygulamasını göstermektedir:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
refHandle = postRef.observe(DataEventType.value, with: { snapshot in
  // ...
})

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
_refHandle = [_postRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
  NSDictionary *postDict = snapshot.value;
  // ...
}];

Dinleyici alır FIRDataSnapshot onun etkinliğin anda veri tabanında belirli bir konumda verileri içeren value özelliği. Aşağıdaki gibi uygun yerel türü, değer atayabilirsiniz NSDictionary . Bir veri konumda bulunuyorsa, value olan nil .

Verileri bir kez oku

getData() kullanarak bir kez okuyun

SDK, uygulamanız ister çevrimiçi ister çevrimdışı olsun, veritabanı sunucularıyla etkileşimleri yönetmek için tasarlanmıştır.

Genel olarak, arka uçtan verilerde yapılan güncellemelerden haberdar olmak için verileri okumak için yukarıda açıklanan değer olayları tekniklerini kullanmalısınız. Bu teknikler, kullanımınızı ve faturalandırmanızı azaltır ve kullanıcılarınıza çevrimiçi ve çevrimdışı olduklarında en iyi deneyimi sunmak için optimize edilmiştir.

Eğer sadece bir kez veri gerekiyorsa, kullanabilirsiniz getData() veritabanından verilerin anlık görüntüsünü alır. Eğer herhangi bir nedenle getData() sunucu değeri döndürmek edemez, istemci yerel depolama önbelleği soruşturma ve değeri hala bulunmazsa bir hata döndürür.

Aşağıdaki örnek, bir kullanıcının herkese açık kullanıcı adının veritabanından tek seferde alınmasını gösterir:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
ref.child("users/\(uid)/username").getData(completion:  { error, snapshot in
  guard error == nil else {
    print(error!.localizedDescription)
    return;
  }
  let userName = snapshot.value as? String ?? "Unknown";
});

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
NSString *userPath = [NSString stringWithFormat:@"users/%@/username", uid];
[[ref child:userPath] getDataWithCompletionBlock:^(NSError * _Nullable error, FIRDataSnapshot * _Nonnull snapshot) {
  if (error) {
    NSLog(@"Received an error %@", error);
    return;
  }
  NSString *userName = snapshot.value;
}];

Gereksiz yere kullanılması getData() bant genişliği kullanımını arttırmak ve yukarıda gösterildiği gibi gerçek zamanlı bir dinleyici kullanılarak önlenebilir performans kaybı, yol açabilir.

Bir gözlemci ile verileri bir kez okuyun

Bazı durumlarda, sunucuda güncellenmiş bir değer olup olmadığını kontrol etmek yerine yerel önbellekteki değerin hemen döndürülmesini isteyebilirsiniz. Bu gibi durumlarda kullanabileceğiniz observeSingleEventOfType hemen yerel disk önbellekten veri almak için.

Bu, yalnızca bir kez yüklenmesi gereken ve sık sık değişmesi beklenmeyen veya etkin dinleme gerektirmeyen veriler için kullanışlıdır. Örneğin, önceki örneklerdeki blog uygulaması, bir kullanıcı yeni bir gönderi yazmaya başladığında profilini yüklemek için bu yöntemi kullanır:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
let userID = Auth.auth().currentUser?.uid
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { snapshot in
  // Get user value
  let value = snapshot.value as? NSDictionary
  let username = value?["username"] as? String ?? ""
  let user = User(username: username)

  // ...
}) { error in
  print(error.localizedDescription)
}

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
NSString *userID = [FIRAuth auth].currentUser.uid;
[[[_ref child:@"users"] child:userID] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
  // Get user value
  User *user = [[User alloc] initWithUsername:snapshot.value[@"username"]];

  // ...
} withCancelBlock:^(NSError * _Nonnull error) {
  NSLog(@"%@", error.localizedDescription);
}];

Verileri güncelleme veya silme

Belirli alanları güncelle

Aynı anda kullanmak, diğer alt düğümlerin üzerine yazmadan bir düğümün belirli çocuklarına yazmak için updateChildValues yöntemi.

Çağırırken updateChildValues , sen anahtarı için bir yolu belirterek düşük seviyede bir alt değerleri güncelleyebilirsiniz. Veri daha iyi ölçekli birden çok yerde saklanıyorsa, kullandığınız verilerin tüm örneklerini güncelleyebilirsiniz veri fan-out . Örneğin, bir sosyal blog uygulaması bir gönderi oluşturmak ve bunu aynı anda en son etkinlik akışına ve gönderiyi paylaşan kullanıcının etkinlik akışına güncellemek isteyebilir. Bunu yapmak için blog uygulaması şöyle bir kod kullanır:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
guard let key = ref.child("posts").childByAutoId().key else { return }
let post = ["uid": userID,
            "author": username,
            "title": title,
            "body": body]
let childUpdates = ["/posts/\(key)": post,
                    "/user-posts/\(userID)/\(key)/": post]
ref.updateChildValues(childUpdates)

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
NSString *key = [[_ref child:@"posts"] childByAutoId].key;
NSDictionary *post = @{@"uid": userID,
                       @"author": username,
                       @"title": title,
                       @"body": body};
NSDictionary *childUpdates = @{[@"/posts/" stringByAppendingString:key]: post,
                               [NSString stringWithFormat:@"/user-posts/%@/%@/", userID, key]: post};
[_ref updateChildValues:childUpdates];

Bu örnek kullanır childByAutoId tüm kullanıcılar için mesajları içeren düğümünde bir yayın oluşturma /posts/$postid ve eşzamanlı ile anahtarı almak getKey() . Anahtar o zaman en Kullanıcı mesajlarının ikinci giriş oluşturmak için kullanılabilir /user-posts/$userid/$postid .

Bu yolları kullanarak, tek bir çağrıyla JSON ağacında birden fazla konuma eşzamanlı güncelleştirmeler gerçekleştirebilen updateChildValues böyle bu örnek her iki konumda da yeni yayın oluşturulur nasıl gibi. Bu şekilde yapılan eşzamanlı güncellemeler atomiktir: ya tüm güncellemeler başarılı olur ya da tüm güncellemeler başarısız olur.

Bir Tamamlama Bloğu Ekle

Verilerinizin ne zaman teslim edildiğini bilmek istiyorsanız, bir tamamlama bloğu ekleyebilirsiniz. Hem setValue ve updateChildValues yazma veritabanına taahhüt edilmiştir çağrılan isteğe bağlı bir tamamlama bloğu alır. Bu dinleyici, hangi verilerin kaydedildiğini ve hangi verilerin hala senkronize edildiğini takip etmek için faydalı olabilir. Çağrı başarısız olursa, dinleyiciye hatanın neden oluştuğunu belirten bir hata nesnesi iletilir.

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
ref.child("users").child(user.uid).setValue(["username": username]) {
  (error:Error?, ref:DatabaseReference) in
  if let error = error {
    print("Data could not be saved: \(error).")
  } else {
    print("Data saved successfully!")
  }
}

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
[[[_ref child:@"users"] child:user.uid] setValue:@{@"username": username} withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  if (error) {
    NSLog(@"Data could not be saved: %@", error);
  } else {
    NSLog(@"Data saved successfully.");
  }
}];

Verileri sil

Silme verilere en basit yolu çağırmaktır removeValue bu verilerin konumun referansı üzerine.

Ayrıca belirterek silebilirsiniz nil gibi başka yazma işlemi için değer olarak setValue veya updateChildValues . Sen ile bu tekniği kullanabilirsiniz updateChildValues tek API çağrısında birden fazla çocuk silmek için.

Dinleyicileri ayır

Bir ayrılırken Gözlemciler verileri otomatik olarak senkronize bitmiyor ViewController . Bir gözlemci düzgün bir şekilde kaldırılmazsa, verileri yerel belleğe eşitlemeye devam eder. Bir gözlemci artık gerekli olduğunda, ilişkili geçirerek çıkarmak FIRDatabaseHandle için removeObserverWithHandle yöntem.

Eğer bir referansa geri arama bloğunu eklediğinizde, bir FIRDatabaseHandle döndürülür. Bu tutamaçlar, geri arama bloğunu kaldırmak için kullanılabilir.

Bir veritabanı başvurusuna birden çok dinleyici eklendiyse, bir olay oluşturulduğunda her bir dinleyici çağrılır. O yerde verileri senkronize etmeyi durdurma için, çağırarak bir yerde bütün gözlemciler kaldırmalısınız removeAllObservers yöntemi.

Arayan removeObserverWithHandle veya removeAllObservers otomatik olarak alt düğümler üzerinde kayıtlı dinleyicileri kaldırmaz bir dinleyici üzerinde; bunları kaldırmak için bu referansları veya tutamaçları da takip etmelisiniz.

Verileri işlem olarak kaydedin

Böyle sayıcı olarak eşzamanlı değişiklikler, tarafından bozulmuş olabilir verilerle çalışırken, bir kullanabilir işlem operasyonu . Bu işleme iki argüman verirsiniz: bir güncelleme işlevi ve isteğe bağlı bir tamamlama geri çağrısı. güncelleme işlevi, verilerin mevcut durumunu bir argüman olarak alır ve yazmak istediğiniz yeni istenen durumu döndürür.

Örneğin, örnek sosyal blog uygulamasında, kullanıcıların gönderilere yıldız eklemesine ve yıldızları kaldırmasına ve bir gönderinin kaç yıldız aldığını aşağıdaki gibi takip etmesine izin verebilirsiniz:

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
  if var post = currentData.value as? [String: AnyObject],
    let uid = Auth.auth().currentUser?.uid {
    var stars: [String: Bool]
    stars = post["stars"] as? [String: Bool] ?? [:]
    var starCount = post["starCount"] as? Int ?? 0
    if let _ = stars[uid] {
      // Unstar the post and remove self from stars
      starCount -= 1
      stars.removeValue(forKey: uid)
    } else {
      // Star the post and add self to stars
      starCount += 1
      stars[uid] = true
    }
    post["starCount"] = starCount as AnyObject?
    post["stars"] = stars as AnyObject?

    // Set value and report transaction success
    currentData.value = post

    return TransactionResult.success(withValue: currentData)
  }
  return TransactionResult.success(withValue: currentData)
}) { error, committed, snapshot in
  if let error = error {
    print(error.localizedDescription)
  }
}

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) {
  NSMutableDictionary *post = currentData.value;
  if (!post || [post isEqual:[NSNull null]]) {
    return [FIRTransactionResult successWithValue:currentData];
  }

  NSMutableDictionary *stars = post[@"stars"];
  if (!stars) {
    stars = [[NSMutableDictionary alloc] initWithCapacity:1];
  }
  NSString *uid = [FIRAuth auth].currentUser.uid;
  int starCount = [post[@"starCount"] intValue];
  if (stars[uid]) {
    // Unstar the post and remove self from stars
    starCount--;
    [stars removeObjectForKey:uid];
  } else {
    // Star the post and add self to stars
    starCount++;
    stars[uid] = @YES;
  }
  post[@"stars"] = stars;
  post[@"starCount"] = @(starCount);

  // Set value and report transaction success
  currentData.value = post;
  return [FIRTransactionResult successWithValue:currentData];
} andCompletionBlock:^(NSError * _Nullable error,
                       BOOL committed,
                       FIRDataSnapshot * _Nullable snapshot) {
  // Transaction completed
  if (error) {
    NSLog(@"%@", error.localizedDescription);
  }
}];

Bir işlemin kullanılması, birden fazla kullanıcının aynı gönderiye aynı anda yıldız vermesi veya istemcinin eski verileri olması durumunda yıldız sayılarının yanlış olmasını önler. Bulunan değer FIRMutableData sınıfında başlangıçta müşterinin bilinen son yolunun değeri, ya da nil hiçbiri varsa. Sunucu, başlangıç ​​değeri ile mevcut değeri karşılaştırır ve eğer değerler eşleşirse işlemi kabul eder veya reddeder. İşlem reddedilirse, sunucu, işlemi güncellenen değerle yeniden çalıştıran istemciye mevcut değeri döndürür. Bu, işlem kabul edilene veya çok fazla deneme yapılana kadar tekrarlanır.

Atomik sunucu tarafı artışları

Yukarıdaki kullanım durumunda, veritabanına iki değer yazıyoruz: gönderiye yıldız atan/yıldızı kaldıran kullanıcının kimliği ve artan yıldız sayısı. Kullanıcının gönderiye yıldız eklediğini zaten biliyorsak, işlem yerine atomik bir artış işlemi kullanabiliriz.

Süratli

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
let updates = [
  "posts/\(postID)/stars/\(userID)": true,
  "posts/\(postID)/starCount": ServerValue.increment(1),
  "user-posts/\(postID)/stars/\(userID)": true,
  "user-posts/\(postID)/starCount": ServerValue.increment(1)
] as [String : Any]
Database.database().reference().updateChildValues(updates);

Amaç-C

Not: Bu Firebase ürün App Klip hedefte kullanılamaz.
NSDictionary *updates = @{[NSString stringWithFormat: @"posts/%@/stars/%@", postID, userID]: @TRUE,
                        [NSString stringWithFormat: @"posts/%@/starCount", postID]: [FIRServerValue increment:@1],
                        [NSString stringWithFormat: @"user-posts/%@/stars/%@", postID, userID]: @TRUE,
                        [NSString stringWithFormat: @"user-posts/%@/starCount", postID]: [FIRServerValue increment:@1]};
[[[FIRDatabase database] reference] updateChildValues:updates];

Bu kod bir işlem işlemi kullanmaz, bu nedenle çakışan bir güncelleme varsa otomatik olarak yeniden çalıştırılmaz. Ancak artırma işlemi doğrudan veritabanı sunucusunda gerçekleştiği için çakışma olasılığı yoktur.

Bir kullanıcının daha önce yıldız eklemiş olduğu bir gönderiye yıldız eklemesi gibi uygulamaya özel çakışmaları algılamak ve reddetmek istiyorsanız, bu kullanım durumu için özel güvenlik kuralları yazmalısınız.

Verilerle çevrimdışı çalışın

Bir istemci ağ bağlantısını kaybederse uygulamanız düzgün şekilde çalışmaya devam eder.

Bir Firebase veritabanına bağlanan her istemci, herhangi bir etkin verinin kendi dahili sürümünü tutar. Veri yazıldığında, önce bu yerel sürüme yazılır. Firebase istemcisi daha sonra bu verileri uzak veritabanı sunucuları ve diğer istemcilerle "en iyi çaba" temelinde senkronize eder.

Sonuç olarak, veritabanına yapılan tüm yazma işlemleri, sunucuya herhangi bir veri yazılmadan hemen önce yerel olayları tetikler. Bu, uygulamanızın ağ gecikmesinden veya bağlantıdan bağımsız olarak yanıt vermeye devam edeceği anlamına gelir.

Bağlantı yeniden kurulduğunda, uygulamanız uygun olay kümesini alır, böylece istemci herhangi bir özel kod yazmak zorunda kalmadan mevcut sunucu durumuyla eşitlenir.

Biz de çevrimdışı davranış hakkında daha fazla konuşacağız daha yaklaşık çevrimiçi ve çevrimdışı yetenekleri öğrenin .

Sonraki adımlar