Xamarin.iOS ile iCloud kullanma
iOS 5'te iCloud depolama API'si, uygulamaların kullanıcı belgelerini ve uygulamaya özgü verileri merkezi bir konuma kaydetmesini ve bu öğelere kullanıcının tüm cihazlarından erişmesini sağlar.
Dört tür depolama alanı vardır:
Anahtar-Değer depolama: Bir kullanıcının diğer cihazlarda uygulamanıza küçük miktarlarda veri paylaşmak için.
UIDocument depolama alanı: UIDocument alt sınıflarını kullanarak belgeleri ve diğer verileri kullanıcının iCloud hesabında depolamak için.
CoreData - SQLite veritabanı depolama alanı.
Tek tek dosyalar ve dizinler - doğrudan dosya sisteminde çok sayıda farklı dosyayı yönetmek için.
Bu belgede ilk iki tür (Key-Value çiftleri ve UIDocument alt sınıfları) ve bu özelliklerin Xamarin.iOS'ta nasıl kullanılaları elerilmektedir.
Önemli
Apple, geliştiricilerin Avrupa Birliği'nin (GDPR) Genel Veri Koruma Yönetmeliği araçlar sağlar.
Gereksinimler
- Xamarin.iOS'un en son kararlı sürümü
- Xcode 10
- Mac için Visual Studio veya Visual Studio 2019.
iCloud geliştirme için hazırlanma
Uygulamaların hem Apple Sağlama Portalında hem de projenin kendisinde iCloud'u kullanmak üzere yapılandırılması gerekir. iCloud için geliştirmeden (veya örnekleri denmeden) önce aşağıdaki adımları izleyin.
Bir uygulamayı iCloud'a erişmek üzere doğru şekilde yapılandırmak için:
TeamID'nizi bulun - Developer.apple.com Merkezi'nde oturum açın ve Takım Kimliğinizi (veya tek geliştiricilerin Bireysel Kimliğini) almak için Üye Merkezi Hesap Geliştirici Hesabı Özeti'ne bakın. 10 karakterlik bir dize (örneğin, A93A5CM278) olur. Bu, "kapsayıcı tanımlayıcısının" bir bölümünü oluşturur.
Yeni bir Uygulama Kimliği oluşturma - Uygulama Kimliği oluşturmak için Cihaz Sağlama kılavuzunun Mağaza Teknolojileri için Sağlama bölümünde açıklanan adımları izleyin ve izin verilen bir hizmet olarak iCloud'u kontrol edin:
Yeni sağlama profili oluşturma - Sağlama Profili oluşturmak için Cihaz Sağlama kılavuzunda açıklanan adımları izleyin.
Kapsayıcı Tanımlayıcısını Entitlements.plist'e ekleyin; kapsayıcı tanımlayıcısı biçimi olur. Daha fazla bilgi için Yetkilendirmelerle Çalışma kılavuzuna bakın.
Proje özelliklerini yapılandırma - Info.plist dosyasında, Paket Tanımlayıcısı'nın Uygulama Kimliği oluşturulurken ayarlanmış Paket Kimliği ile eş olduğundan emin olun; iOS Paket Paketi İmzalama, iCloud hesabıyla bir Uygulama Kimliği içeren bir Sağlama Profili App Service ve Özel Yetkilendirmeler dosyası seçilidir. Bunların hepsi proje Özellikler Visual Studio içinde yapılabilir.
Cihazda iCloud'u etkinleştirme - iCloud'Ayarlar gidin ve cihazın oturum açtığınızdan emin olun. Belge Verileri seçeneğini belirleyin ve bu seçeneği belirleyin.
iCloud'u test etmek için bir cihaz kullansanız da Simülatörde çalışmaz. Aslında, iCloud'u çalışır olarak görmek için tüm cihazların aynı Apple kimliğiyle oturumlarına sahip iki veya daha fazla cihaza ihtiyacınız vardır.
Key-Value Depolama
Anahtar-değer depolama, bir kullanıcının cihazlarda kalıcı olarak kalıcı olması gibi, bir kitap veya dergisinde görüntülen son sayfası gibi küçük miktarlardaki verilere yöneliktir. Anahtar-değer depolaması, verileri backing için kullanılmamalı.
Anahtar-değer depolama kullanırken dikkat etmek gereken bazı sınırlamalar vardır:
En büyük anahtar boyutu - Anahtar adları 64 bayttan uzun olamaz.
Maksimum değer boyutu - Tek bir değerde 64 kilobayttan fazla depoamazsiniz.
Bir uygulama için en fazla anahtar-değer deposu boyutu - Uygulamalar toplamda en fazla 64 kilobayt anahtar-değer verisi depolar. Anahtarları bu sınırın ötesinde ayarlama girişimleri başarısız olur ve önceki değer kalıcı olur.
Veri türleri - Yalnızca dizeler, sayılar ve booleanlar gibi temel türler depolanmış olabilir.
iCloudKeyValue örneği, nasıl çalıştığını gösteriyor. Örnek kod, her cihaz için adlı bir anahtar oluşturur: Bu anahtarı bir cihazda ayarp değerin başkalarına yayılmasını izleyebilirsiniz. Ayrıca herhangi bir cihazda düzenlenebilir "Paylaşılan" adlı bir anahtar da oluşturur. Aynı anda birçok cihazda düzenleme yaptıysanız iCloud hangi değerin "kazanır" (değişiklikte bir zaman damgası kullanarak) olduğuna karar verir ve yayılır.
Bu ekran görüntüsü kullanım örneğini gösterir. iCloud'dan değişiklik bildirimleri alınca ekranın en altındaki kayan metin görünümünde yazdırılır ve giriş alanlarında güncelleştirilir.
Verileri ayarlama ve alma
Bu kod, bir dize değerinin nasıl ayar olduğunu gösterir.
var store = NSUbiquitousKeyValueStore.DefaultStore;
store.SetString("testkey", "VALUE IN THE CLOUD"); // key and value
store.Synchronize();
Eşitleme çağrısı, değerin yalnızca yerel disk depolamada kalıcı olarak depolanmasına sağlar. iCloud ile eşitleme arka planda gerçekleşir ve uygulama kodu tarafından "zor kullanılamaz". İyi ağ bağlantısıyla eşitleme genellikle 5 saniye içinde olur, ancak ağ zayıfsa (veya bağlantısı kesildi ise) bir güncelleştirme çok daha uzun sürebilir.
Bu kodla bir değer almak için:
var store = NSUbiquitousKeyValueStore.DefaultStore;
display.Text = store.GetString("testkey");
Değer yerel veri deposundan alınır. Bu yöntem, "en son" değeri almak için iCloud sunucularına başvurarak denemez. iCloud, yerel veri depolarını kendi zaman çizelgesine göre güncelleştirecek.
Veri silme
Anahtar-değer çiftini tamamen kaldırmak için Remove yöntemini şu şekilde kullanın:
var store = NSUbiquitousKeyValueStore.DefaultStore;
store.Remove("testkey");
store.Synchronize();
Değişiklikleri Gözlemle
Bir uygulama, değerlerin iCloud tarafından değiştirilmesi için uygulamasına gözlemci ekleyerek bildirim de NSNotificationCenter.DefaultCenter alır.
KeyValueViewController.cs yönteminden gelen aşağıdaki kod, bu bildirimleri dinlemeyi ve değiştirilen anahtarların listesini oluşturmayı gösterir:
keyValueNotification =
NSNotificationCenter.DefaultCenter.AddObserver (
NSUbiquitousKeyValueStore.DidChangeExternallyNotification, notification => {
Console.WriteLine ("Cloud notification received");
NSDictionary userInfo = notification.UserInfo;
var reasonNumber = (NSNumber)userInfo.ObjectForKey (NSUbiquitousKeyValueStore.ChangeReasonKey);
nint reason = reasonNumber.NIntValue;
var changedKeys = (NSArray)userInfo.ObjectForKey (NSUbiquitousKeyValueStore.ChangedKeysKey);
var changedKeysList = new List<string> ();
for (uint i = 0; i < changedKeys.Count; i++) {
var key = changedKeys.GetItem<NSString> (i); // resolve key to a string
changedKeysList.Add (key);
}
// now do something with the list...
});
Kodunuz daha sonra değiştirilen anahtarların listesiyle bazı eylemlerde olabilir; örneğin, bu anahtarların yerel kopyasını güncelleştirebilir veya kullanıcı arabirimini yeni değerlerle güncelleştirebilir.
Olası değişiklik nedenleri: ServerChange (0), InitialSyncChange (1) veya QuotaViolationChange (2). Nedene erişerek gerekirse farklı işlemler gerçekleştirin (örneğin, QuotaViolationChangesonucu olarak bazı anahtarları kaldırmanız gerekebilir).
Belge Depolama
iCloud Document Depolama, uygulamanıza (ve kullanıcıya) önemli verileri yönetmek için tasarlanmıştır. Uygulamanıza gereken dosyaları ve diğer verileri yönetmek için, aynı zamanda kullanıcının tüm cihazlarda iCloud tabanlı yedekleme ve paylaşım işlevselliği sağlamak için kullanılabilir.
Bu diyagramda her şeyi nasıl bir araya getirdiklerini gösterir. Her cihazda yerel depolama alanına (UbiquityContainer) kayıtlı veriler vardır ve işletim sisteminin iCloud Daemon'ı bulutta veri göndererek almayla ilgilenmektedir. Eşzamanlı erişimi önlemek için UbiquityContainer'a tüm dosya erişiminin FilePresenter/FileCoordinator aracılığıyla yapılması gerekir. sınıfı UIDocument sizin için bu öğeleri kullanır; bu örnekte UIDocument'ın nasıl kullanılası gösterir.
iCloudUIDoc örneği, tek bir metin UIDocument alanı içeren basit bir alt sınıf uygulamadır. Metin bir içinde işlenir ve düzenlemeler iCloud tarafından diğer cihazlara kırmızı renkle gösterilen UITextView bir bildirim iletisiyle birlikte yayılır. Örnek kod, çakışma çözümü gibi daha gelişmiş iCloud özellikleriyle uğraşmak zorunda değildir.
Bu ekran görüntüsü, örnek uygulamayı gösterir. Metni değiştirdikten ve UpdateChangeCount tuşuna bastıktan sonra belge iCloud üzerinden diğer cihazlarla eşitlenir.
iCloudUIDoc örneğinin beş parçası vardır:
UbiquityContainer'a erişme- iCloud'un etkin olup olmadığını ve etkinse uygulamanın iCloud depolama alanına giden yolu belirler.
UIDocument alt sınıfı oluşturma - iCloud depolama ile model nesneleriniz arasında ara sınıf oluşturun.
iCloud belgelerini bulma ve açma -
NSPredicateiCloud belgelerini bulmak ve açmak için ve kullanın.iCloud belgelerini görüntüleme - kullanıcı arabirimi denetimleriyle etkileşim kurabilirsiniz.
iCloud belgelerini kaydetme - Kullanıcı arabiriminde yapılan değişikliklerin diskte ve iCloud'da kalıcı olduğundan emin olun.
Tüm iCloud işlemleri zaman uyumsuz olarak çalıştırarak bir şeyin olmasını beklerken engellemelerini engeller. Örnekte bunu gerçekleştirmenin üç farklı yolu vardır:
İş parçacıkları - ana iş parçacığının GetUrlForUbiquityContainer engellenmesini önlemek için ilk çağrısında başka bir iş parçacığında yapılır.
NotificationCenter - tamamlandı gibi zaman uyumsuz işlemler olduğunda bildirimlere kaydolma.
Tamamlama İşleyicileri - gibi zaman uyumsuz işlemlerin tamamlanmasında çalıştıracak yöntemleri geçirme.
UbiquityContainer'a erişme
iCloud Document Depolama kullanmanın ilk adımı, iCloud'un etkin olup olmadığını ve etkinse "ubiquity kapsayıcısı" konumunu (iCloud özellikli dosyaların cihazda depolandığı dizin) belirlemektir.
Bu kod, AppDelegate.FinishedLaunching örneğin yöntemindedir.
// GetUrlForUbiquityContainer is blocking, Apple recommends background thread or your UI will freeze
ThreadPool.QueueUserWorkItem (_ => {
CheckingForiCloud = true;
Console.WriteLine ("Checking for iCloud");
var uburl = NSFileManager.DefaultManager.GetUrlForUbiquityContainer (null);
// OR instead of null you can specify "TEAMID.com.your-company.ApplicationName"
if (uburl == null) {
HasiCloud = false;
Console.WriteLine ("Can't find iCloud container, check your provisioning profile and entitlements");
InvokeOnMainThread (() => {
var alertController = UIAlertController.Create ("No \uE049 available",
"Check your Entitlements.plist, BundleId, TeamId and Provisioning Profile!", UIAlertControllerStyle.Alert);
alertController.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Destructive, null));
viewController.PresentViewController (alertController, false, null);
});
} else { // iCloud enabled, store the NSURL for later use
HasiCloud = true;
iCloudUrl = uburl;
Console.WriteLine ("yyy Yes iCloud! {0}", uburl.AbsoluteUrl);
}
CheckingForiCloud = false;
});
Örnek bunu yapmasa da Apple, ön plana her uygulama geldiğinde GetUrlForUbiquityContainer'ın çağrılması önerilir.
UIDocument Alt Sınıfı Oluşturma
Tüm iCloud dosyaları ve dizinleri (yani UbiquityContainer dizininde depolanan her şey) NSFileManager yöntemleri kullanılarak yönetilmeli, NSFilePresenter protokolü uygulanarak ve NSFileCoordinator aracılığıyla yazarak yazabilir. Bunların hepsini sizin yazmanın en basit yolu kendiniz yazmak değil, hepsini sizin için yapacak olan UIDocument alt sınıfıdır.
iCloud ile çalışmak için UIDocument alt sınıfına uygulamanız gereken yalnızca iki yöntem vardır:
LoadFromContents - dosya içeriğinin NSData'sı içinde, model sınıflarınızı/sınıflarınızı açmanızı sağlar.
ContentsForType - diske (ve Buluta) kaydetmeniz için model sınıf/es'nizin NSData gösterimini sağlamak için istekte bulunur.
iCloudUIDoc\DocumentDocument.cs'den alınan bu örnek kod, UIDocument'ın nasıl uygulandığını gösterir.
public class MonkeyDocument : UIDocument
{
// the 'model', just a chunk of text in this case; must easily convert to NSData
NSString dataModel;
// model is wrapped in a nice .NET-friendly property
public string DocumentString {
get {
return dataModel.ToString ();
}
set {
dataModel = new NSString (value);
}
}
public MonkeyDocument (NSUrl url) : base (url)
{
DocumentString = "(default text)";
}
// contents supplied by iCloud to display, update local model and display (via notification)
public override bool LoadFromContents (NSObject contents, string typeName, out NSError outError)
{
outError = null;
Console.WriteLine ("LoadFromContents({0})", typeName);
if (contents != null)
dataModel = NSString.FromData ((NSData)contents, NSStringEncoding.UTF8);
// LoadFromContents called when an update occurs
NSNotificationCenter.DefaultCenter.PostNotificationName ("monkeyDocumentModified", this);
return true;
}
// return contents for iCloud to save (from the local model)
public override NSObject ContentsForType (string typeName, out NSError outError)
{
outError = null;
Console.WriteLine ("ContentsForType({0})", typeName);
Console.WriteLine ("DocumentText:{0}",dataModel);
NSData docData = dataModel.Encode (NSStringEncoding.UTF8);
return docData;
}
}
Bu durumda veri modeli çok basittir; tek bir metin alanıdır. Veri modeliniz, xml belgesi veya ikili veriler gibi gerektiğinde karmaşık olabilir. UIDocument uygulamasının birincil rolü, model sınıflarınızı ve diske kaydedilebilir/yüklenebilir bir NSData gösterimini çevirmektir.
iCloud Belgelerini Bulma ve Açma
Örnek uygulama yalnızca tek bir dosyayla (test.txt) ilgilener. Bu nedenle AppDelegate.cs dosyasındaki kod, özel olarak bu dosya adını için bir ve NSMetadataQuery oluşturur. NSMetadataQueryzaman uyumsuz olarak çalışır ve tamam olduğunda bir bildirim gönderir. DidFinishGathering bildirim gözlemcisi tarafından çağrılır, sorguyu durdurur ve dosyayı yüklemek ve bir içinde görüntülemek için tamamlama işleyicisi ile yöntemini kullanan LoadDocument'i UIDocument.OpenMonkeyDocumentViewController çağırır.
string monkeyDocFilename = "test.txt";
void FindDocument ()
{
Console.WriteLine ("FindDocument");
query = new NSMetadataQuery {
SearchScopes = new NSObject [] { NSMetadataQuery.UbiquitousDocumentsScope }
};
var pred = NSPredicate.FromFormat ("%K == %@", new NSObject[] {
NSMetadataQuery.ItemFSNameKey, new NSString (MonkeyDocFilename)
});
Console.WriteLine ("Predicate:{0}", pred.PredicateFormat);
query.Predicate = pred;
NSNotificationCenter.DefaultCenter.AddObserver (
this,
new Selector ("queryDidFinishGathering:"),
NSMetadataQuery.DidFinishGatheringNotification,
query
);
query.StartQuery ();
}
[Export ("queryDidFinishGathering:")]
void DidFinishGathering (NSNotification notification)
{
Console.WriteLine ("DidFinishGathering");
var metadataQuery = (NSMetadataQuery)notification.Object;
metadataQuery.DisableUpdates ();
metadataQuery.StopQuery ();
NSNotificationCenter.DefaultCenter.RemoveObserver (this, NSMetadataQuery.DidFinishGatheringNotification, metadataQuery);
LoadDocument (metadataQuery);
}
void LoadDocument (NSMetadataQuery metadataQuery)
{
Console.WriteLine ("LoadDocument");
if (metadataQuery.ResultCount == 1) {
var item = (NSMetadataItem)metadataQuery.ResultAtIndex (0);
var url = (NSUrl)item.ValueForAttribute (NSMetadataQuery.ItemURLKey);
doc = new MonkeyDocument (url);
doc.Open (success => {
if (success) {
Console.WriteLine ("iCloud document opened");
Console.WriteLine (" -- {0}", doc.DocumentString);
viewController.DisplayDocument (doc);
} else {
Console.WriteLine ("failed to open iCloud document");
}
});
} // TODO: if no document, we need to create one
}
iCloud Belgelerini Görüntüleme
UIDocument'ın görüntülenmesi diğer model sınıflarında farklı olmaması gerekir. Özellikler kullanıcı tarafından düzenleniyor ve sonra modele geri yazıldığı için kullanıcı arabirimi denetimlerde görüntüleniyor.
iCloudUIDoc\DocumentDocumentViewController.cs örneğinde, bir içindeDocument metni görüntülenir. ViewDidLoad yönteminde gönderilen bildirimi MonkeyDocument.LoadFromContents dinler. LoadFromContents iCloud dosya için yeni veriler içerir ve böylece bildirim belgenin güncelleştirilmiş olduğunu gösterir.
NSNotificationCenter.DefaultCenter.AddObserver (this,
new Selector ("dataReloaded:"),
new NSString ("monkeyDocumentModified"),
null
);
Örnek kod bildirimi işleyicisi, kullanıcı arabirimini güncelleştirmek için bir yöntem (bu örnekte herhangi bir çakışma algılama veya çözüm olmadan) yöntemini çağırıyor.
[Export ("dataReloaded:")]
void DataReloaded (NSNotification notification)
{
doc = (MonkeyDocument)notification.Object;
// we just overwrite whatever was being typed, no conflict resolution for now
docText.Text = doc.DocumentString;
}
iCloud Belgelerini Kaydetme
iCloud'a UIDocument eklemek için doğrudan UIDocument.Save çağırabilirsiniz (yalnızca yeni belgeler için) veya kullanarak mevcut bir dosyayı NSFileManager.DefaultManager.SetUbiquitious taşıyabilirsiniz. Örnek kod, bu kodla doğrudan ubiquity kapsayıcısı içinde yeni bir belge oluşturur (burada biri işlem için, diğeri Open için olmak üzere iki tamamlama Save işleyicisi vardır):
var docsFolder = Path.Combine (iCloudUrl.Path, "Documents"); // NOTE: Documents folder is user-accessible in Settings
var docPath = Path.Combine (docsFolder, MonkeyDocFilename);
var ubiq = new NSUrl (docPath, false);
var monkeyDoc = new MonkeyDocument (ubiq);
monkeyDoc.Save (monkeyDoc.FileUrl, UIDocumentSaveOperation.ForCreating, saveSuccess => {
Console.WriteLine ("Save completion:" + saveSuccess);
if (saveSuccess) {
monkeyDoc.Open (openSuccess => {
Console.WriteLine ("Open completion:" + openSuccess);
if (openSuccess) {
Console.WriteLine ("new document for iCloud");
Console.WriteLine (" == " + monkeyDoc.DocumentString);
viewController.DisplayDocument (monkeyDoc);
} else {
Console.WriteLine ("couldn't open");
}
});
} else {
Console.WriteLine ("couldn't save");
}
Belgede yapılan sonraki değişiklikler doğrudan "kayıtlı" değildir, bunun yerine ile değiştiğini söyleriz ve otomatik olarak diske kaydetme UIDocumentUpdateChangeCount işlemi zamanlar:
doc.UpdateChangeCount (UIDocumentChangeKind.Done);
iCloud Belgelerini Yönetme
Kullanıcılar, iCloud belgelerini uygulamanın dışındaki "ubiquity kapsayıcısı" belgeler dizininde Ayarlar; dosya listesini görüntüp silmek için çekerek yönetebilir. Uygulama kodu, belgelerin kullanıcı tarafından silindiğinde durumu işleyene kadar devam edemelidir. İç uygulama verilerini Belgeler dizininde depolamayın.
Ayrıca kullanıcılar, iCloud özellikli bir uygulamayı cihazlarından kaldırmaya ve bu uygulamayla ilgili iCloud belgelerinin durumu hakkında bilgi almaya çalışırken de farklı uyarılar alır.
iCloud Yedekleme
iCloud'a yedekleme, geliştiriciler tarafından doğrudan erişilen bir özellik değildir, ancak uygulamanızı tasarlamanız kullanıcı deneyimini etkileyebilir. Apple, geliştiricilerin iOS Depolama izlemeleri için iOS Data Depolama Yönergeleri sağlar.
En önemli nokta, uygulamanın kullanıcı tarafından oluşturulmadan büyük dosyaları depop depolamamasıdır (örneğin, sorun başına yüz artı megabaytlarca içerik depolar bir magazini okuyucu uygulaması). Apple, bu tür verileri iCloud'a yedeklemek ve kullanıcının iCloud kotasını gereksiz yere doldurmak yerine depolamamayı tercih eder.
Bunun gibi büyük miktarlarda veri depoyan uygulamalar, bu verileri, destek gerektirmiyor kullanıcı dizinlerinden biri içinde depolamalı (örn. Önbellekler veya tmp) ya da iCloud'un yedekleme işlemleri sırasında bunları yoksaymalarını için bu dosyalara NSFileManager.SetSkipBackupAttribute bayrak uygulamak için kullanın.
Özet
Bu makalede iOS 5'e dahil edilen yeni iCloud özelliği tanıtıldı. Projenizi iCloud'u kullanmak üzere yapılandırmak için gereken adımları inceledi ve ardından iCloud özelliklerini uygulama örnekleri sağladı.
Anahtar-değer depolama örneği, NSUserPreferences'ın depolanmasına benzer şekilde iCloud'un küçük miktarda veri depolamak için nasıl kullanılageldi. UIDocument örneği, iCloud aracılığıyla birden çok cihaz arasında ne kadar karmaşık verilerin depolana ve eşitlene olduğunu gösterdi.
Son olarak, iCloud Backup'ın ek olarak uygulama tasarımınızı nasıl etkileyeceği hakkında kısa bir tartışma da yer aldı.






