CoreData ve bir REST web hizmeti eşzamansız olarak nasıl eşitlenir ve aynı zamanda REST hataları kullanıcı arabirimine doğru şekilde yayılır


85

Hey, buradaki uygulamamız için model katmanı üzerinde çalışıyorum.

Bazı gereksinimler şu şekildedir:

  1. İPhone OS 3.0+ üzerinde çalışmalıdır.
  2. Verilerimizin kaynağı bir RESTful Rails uygulamasıdır.
  3. Verileri Core Data kullanarak yerel olarak önbelleğe almalıyız.
  4. İstemci kodu (UI denetleyicilerimiz), herhangi bir ağ öğesi hakkında olabildiğince az bilgiye sahip olmalı ve modeli Core Data API ile sorgulamalı / güncellemelidir.

Sunucu güdümlü bir Kullanıcı Deneyimi Oluşturma üzerine WWDC10 Oturum 117'yi kontrol ettim , Amaç Kaynağı , Çekirdek Kaynak ve RestfulCoreData çerçevelerini kontrol etmek için biraz zaman harcadım .

Objective Resource çerçevesi, Core Data ile kendi başına konuşmaz ve yalnızca bir REST istemci uygulamasıdır. Core Resource ve RestfulCoreData, kodunuzda Core Data ile konuştuğunuzu varsayar ve model katmanında arka planda bulunan tüm somunları ve cıvataları çözerler.

Şimdiye kadar her şey yolunda görünüyor ve başlangıçta Core Resource veya RestfulCoreData'nın yukarıdaki tüm gereksinimleri karşılayacağını düşündüm, ancak ... Hiçbirinin doğru şekilde çözülmediği birkaç şey var:

  1. Sunucuya yerel güncellemeler kaydedilirken ana iş parçacığı engellenmemelidir.
  2. Kaydetme işlemi başarısız olursa, hata kullanıcı arayüzüne yayılmalı ve yerel Temel Veri deposuna hiçbir değişiklik kaydedilmemelidir.

Çekirdek Kaynak - (BOOL)save:(NSError **)error, Yönetilen Nesne Bağlamınızı çağırdığınızda tüm isteklerini sunucuya gönderir ve bu nedenle sunucuya bir şekilde başarısız olan temel isteklerin doğru bir NSError örneğini sağlayabilir. Ancak, kaydetme işlemi bitene kadar çağıran iş parçacığını engeller. BAŞARISIZ.

RestfulCoreData, -save:çağrılarınızı olduğu gibi tutar ve istemci iş parçacığı için herhangi bir ek bekleme süresi sağlamaz. Yalnızca izler NSManagedObjectContextDidSaveNotificationve ardından ilgili istekleri bildirim işleyicisindeki sunucuya gönderir. Ama bu şekilde -save:çağrı hep başarıyla tamamlar aslında başarısız olabilir tasarrufu nedeniyle bazı sunucuya yaymak bilmek için bir yol vardır denilen ve istemci kodu (iyi, verilen Çekirdek Veri kaydedilen değişikliklerle tamamdır) 404veya 421ya da her ne sunucu tarafında hata oluştu. Ve dahası, yerel depolama verileri güncellenmiş olur, ancak sunucu değişiklikleri asla bilmez. BAŞARISIZ.

Bu nedenle, tüm bu sorunların üstesinden gelmek için olası bir çözüm / ortak uygulamalar arıyorum:

  1. -save:Ağ istekleri gerçekleşirken arama iş parçacığının her aramada engellenmesini istemiyorum .
  2. Kullanıcı arayüzünde bir şekilde bazı senkronizasyon işlemlerinin yanlış gittiğine dair bildirimler almak istiyorum.
  3. Sunucu istekleri başarısız olursa gerçek Çekirdek Veri kaydının da başarısız olmasını istiyorum.

Herhangi bir fikir?


1
Vay canına, bu soruyu sorarak beni ne kadar zahmetten kurtardığını bilemezsin. Şu anda, her arama yaptığımda (bir .NET web hizmeti olsa da) kullanıcıyı verileri bekletmek için uygulamamı uyguladım. Eşzamansız hale getirmenin bir yolunu düşünüyordum ama nasıl yapılacağını çözemedim. Sağladığınız tüm kaynaklar için teşekkürler!
Tejaswi Yerukalapudi

Harika soru, teşekkür ederim.
Justin

Çekirdek Kaynak bağlantısı kesildi, şimdi nerede barındırıldığını bilen var mı?

Çekirdek Kaynak hala GitHub'da burada barındırılıyor: github.com/mikelaurence/CoreResource
eploko

Orijinal site gitHub'da
eploko

Yanıtlar:


26

Bu kullanım durumu için RestKit'e ( http://restkit.org ) gerçekten bir göz atmalısınız . Uzak JSON kaynaklarını modelleme ve yerel bir Core Data destekli önbelleğe senkronize etme sorunlarını çözmek için tasarlanmıştır. Kullanılabilir ağ olmadığında tamamen önbellekten çalışmak için çevrimdışı modu destekler. Tüm eşitleme, bir arka plan iş parçacığı üzerinde gerçekleşir (ağ erişimi, yük ayrıştırma ve yönetilen nesne bağlamı birleştirme) ve neler olup bittiğini anlayabilmeniz için zengin bir temsilci yöntemleri kümesi vardır.


18

Üç temel bileşen vardır:

  1. UI Eylemi ve CoreData'daki değişikliği sürdürmek
  2. Bu değişikliği sunucuya kadar sürdürmek
  3. Kullanıcı arayüzünü sunucunun yanıtı ile yenileme

Bir NSOperation + NSOperationQueue, ağ isteklerini düzenli tutmaya yardımcı olacaktır. Temsilci protokolü, UI sınıflarınızın ağ isteklerinin hangi durumda olduğunu anlamasına yardımcı olur, örneğin:

@protocol NetworkOperationDelegate
  - (void)operation:(NSOperation *)op willSendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
  - (void)operation:(NSOperation *)op didSuccessfullySendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
  - (void)operation:(NSOperation *)op encounteredAnError:(NSError *)error afterSendingRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
@end

Protokol biçimi elbette özel kullanım durumunuza bağlı olacaktır, ancak esas olarak oluşturduğunuz şey, değişikliklerin sunucunuza "iletilebileceği" bir mekanizmadır.

Daha sonra dikkate alınması gereken UI döngüsü var, kodunuzu temiz tutmak için kaydetme işlevini çağırmak ve değişikliklerin otomatik olarak sunucuya aktarılmasını sağlamak iyi olur. Bunun için NSManagedObjectContextDidSave bildirimlerini kullanabilirsiniz.

- (void)managedObjectContextDidSave:(NSNotification *)saveNotification {
  NSArray *inserted = [[saveNotification userInfo] valueForKey:NSInsertedObjects];
  for (NSManagedObject *obj in inserted) {
    //create a new NSOperation for this entity which will invoke the appropraite rest api
    //add to operation queue
  }

  //do the same thing for deleted and updated objects
}

Ağ işlemlerini eklemek için hesaplama ek yükü oldukça düşük olmalıdır, ancak kullanıcı arayüzünde gözle görülür bir gecikme yaratırsa, varlık kimliklerini kaydetme bildiriminden kolayca alabilir ve işlemleri bir arka plan iş parçacığında oluşturabilirsiniz.

REST API'niz toplu işlemeyi destekliyorsa tüm diziyi tek seferde gönderebilir ve ardından kullanıcı arayüzüne birden çok varlığın senkronize edildiğini bildirebilirsiniz.

Öngördüğüm ve "gerçek" bir çözüm bulunmayan tek sorun, kullanıcının daha fazla değişiklik yapmasına izin verilmesi için değişikliklerinin sunucuya gönderilmesini beklemek istememesidir. Karşılaştığım tek iyi paradigma, kullanıcının nesneleri düzenlemeye devam etmesine ve uygun olduğunda düzenlemelerini toplu halde toplamasına izin vermeniz, yani her kaydetme bildirimine basmamanızdır.


2

Bu bir senkronizasyon sorunu haline gelir ve çözülmesi kolay değildir. İşte yapacağım şey: iPhone kullanıcı arayüzünüzde bir bağlam kullanın ve ardından başka bir bağlam (ve başka bir iş parçacığı) kullanarak verileri web hizmetinizden indirin. Her şey bittiğinde, aşağıda önerilen senkronizasyon / içe aktarma işlemlerinden geçin ve ardından her şey düzgün bir şekilde içe aktarıldıktan sonra kullanıcı arayüzünüzü yenileyin. Ağa erişirken işler kötü giderse, değişiklikleri UI olmayan bağlamda geri alın. Bir sürü iş ama bence buna yaklaşmanın en iyi yolu bu.

Temel Veriler: Verileri Verimli Bir Şekilde İçe Aktarma

Temel Veriler: Değişiklik Yönetimi

Çekirdek Veriler: Temel Verilerle Çoklu İş Parçacığı Oluşturma


0

Diğer iş parçacığında (gerçek sunucu etkileşiminin gerçekleştiği) çalışacak ve ardından sonuç kodunu / hata bilgisini UI iş parçacığı tarafından periyodik olarak kontrol edilecek yarı küresel bir veri koyacak bir geri arama işlevine ihtiyacınız var. Bayrak görevi gören numaranın telgrafının atomik olduğundan emin olun veya bir yarış koşulunuz olacak - diyelim ki hata cevabınız 32 bayt ise bir int'e ihtiyacınız var (atomik erişime sahip olmalı) ve sonra bu int'i koruyun kapalı / yanlış / hazır değil durumunda, daha büyük veri bloğunuz yazılıncaya kadar ve sadece o zaman anahtarı çevirmek için "true" yazın.

İstemci tarafında ilişkili kaydetme için, ya bu verileri saklamanız ve sunucudan bir miktar geri alma seçeneğiniz olduğundan emin oluncaya kadar kaydetmemeniz gerekir - silmenin bir yolu sunucunun başarısız olduğunu söyleyin.

Tam 2 aşamalı kesinleştirme prosedürünü (istemci kaydetme veya silme, sunucu sunucusundan gelen sinyalden sonra başarısız olabilir) sürece asla% 100 güvenli olmayacağına dikkat edin, ancak bu size en azından sunucuya 2 seyahatinize mal olacak ( tek geri alma seçeneğiniz silinirse size 4 mal olabilir).

İdeal olarak, işlemin tüm engelleme sürümünü ayrı bir iş parçacığında yaparsınız, ancak bunun için 4.0'a ihtiyacınız vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.