iCloud ile ilgili temel bilgiler ve kod örneği [kapalı]


86

Yeni başlayan biri olarak iCloud ile mücadele ediyorum. Bazı örnekler var, ancak genellikle oldukça ayrıntılılar (geliştirici forumunda büyük olan iCloud ve CoreData için bir tane var). Elma dokümanlar Tamam, ama hala büyük resmi göremez. Bu yüzden lütfen bana katlanın, bu sorulardan bazıları oldukça temel, ancak muhtemelen cevaplaması kolay.

Bağlam: Çalışan çok basit bir iCloud uygulamam var (tam örnek kod aşağıdadır). Kullanıcıya gösterilen sadece bir UITextView vardır ve onun girdisi text.txt adlı bir dosyaya kaydedilir.

görüntü açıklamasını buraya girin

Txt dosyası buluta gönderilir ve tüm cihazların kullanımına sunulur. Mükemmel çalışıyor, ancak:

Ana sorun: iCloud kullanmayan kullanıcılar ne olacak?

Uygulamamı başlattığımda (aşağıdaki koda bakın), kullanıcının iCloud'u etkinleştirip etkinleştirmediğini kontrol ediyorum. İCloud etkinse, her şey yolunda. Uygulama devam eder ve buluttaki text.txt dosyasını arar. Bulunursa, yükleyecek ve kullanıcıya gösterecektir. Metin.txt bulutta bulunamazsa, basitçe yeni bir text.txt oluşturacak ve bunu kullanıcıya gösterecektir.

Kullanıcının iCloud'u etkin değilse hiçbir şey olmayacaktır. İCloud kullanmayan kullanıcıların metin uygulamamla çalışmaya devam etmesini nasıl sağlayacağım? Yoksa onları görmezden mi gelirim? İCloud olmayan kullanıcılar için ayrı işlevler yazmam gerekir mi? Yani, belgeler klasöründen bir text.txt yüklediğim işlevler?

Apple şöyle yazıyor :

İCloud'daki dosyalara, uygulamanızın sanal alanındaki diğer tüm dosyalara yaptığınız gibi davranın.

Ancak benim durumumda artık 'normal' uygulama sanal alanı yok. Bulutta. Veya her zaman önce text.txt'mi diskten yükleyip ardından daha güncel bir şey olup olmadığını iCloud ile kontrol etmeliyim?

İlgili sorun: Dosya yapısı - Sandbox vs. Cloud

Belki de asıl sorunum, iCloud'un nasıl çalışacağına dair temel bir yanlış anlaşılmadır. Bir UIDocument'in yeni bir örneğini oluşturduğumda, iki yöntemin üzerine yazmam gerekecek. Önce - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outErrorbuluttan dosya almak ve ardından -(id)contentsForType:(NSString *)typeName error:(NSError **)outErrordosyaları buluta almak.

Text.txt dosyasının yerel bir kopyasını korumalı alanıma kaydedecek ayrı işlevler eklemem gerekir mi? Bu, iCloud kullanmayan kullanıcılar için çalışacak mı? İCloud'u anladığım kadarıyla, text.txt'nin yerel bir kopyasını otomatik olarak kaydedecek. Bu nedenle, uygulamamın 'eski' sanal alanına herhangi bir şey kaydetmeme gerek olmamalı (yani, eskiden, iCloud öncesi günlerde olduğu gibi). Şu anda korumalı alanım tamamen boş, ancak bunun doğru olup olmadığını bilmiyorum. Orada başka bir text.txt kopyası saklamalı mıyım? Bu, veri yapımı karmaşık hale getiriyor gibi geliyor ... çünkü bulutta bir text.txt, aygıtımdaki iCloud korumalı alanında (çevrimdışı olsam bile çalışacak) ve üçüncüsü, eski güzel sanal alanda benim uygulamam ...


KODUM: Basit bir iCloud örnek kodu

Bu, genel olarak geliştirici forumunda ve WWDC oturum videosunda bulduğum bir örneğe dayanmaktadır. Asgari düzeye indirdim. MVC yapımın iyi olup olmadığından emin değilim. Model, ideal olmayan AppDelegate içindedir. Daha iyi hale getirmek için herhangi bir öneri bekliyoruz.


DÜZENLEME: Ana soruyu çıkarmaya çalıştım ve [burada] yayınladım. 4


GENEL BAKIŞ:

Genel Bakış

Text.txt dosyasını buluttan yükleyen en önemli bit:

//  AppDelegate.h
//  iCloudText

#import <UIKit/UIKit.h>

@class ViewController;
@class MyTextDocument;

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
    NSMetadataQuery *_query;
}

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;
@property (strong, nonatomic) MyTextDocument *document;

@end

//  AppDelegate.m
//  iCloudText

#import "AppDelegate.h"
#import "MyTextDocument.h"
#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;
@synthesize document = _document;

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

- (void)loadData:(NSMetadataQuery *)query {

    // (4) iCloud: the heart of the load mechanism: if texts was found, open it and put it into _document; if not create it an then put it into _document

    if ([query resultCount] == 1) {
        // found the file in iCloud
        NSMetadataItem *item = [query resultAtIndex:0];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:url];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc openWithCompletionHandler:^(BOOL success) {
            if (success) {
                NSLog(@"AppDelegate: existing document opened from iCloud");
            } else {
                NSLog(@"AppDelegate: existing document failed to open from iCloud");
            }
        }];
    } else {
        // Nothing in iCloud: create a container for file and give it URL
        NSLog(@"AppDelegate: ocument not found in iCloud.");

        NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
        NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:@"text.txt"];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:ubiquitousPackage];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc saveToURL:[doc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            NSLog(@"AppDelegate: new document save to iCloud");
            [doc openWithCompletionHandler:^(BOOL success) {
                NSLog(@"AppDelegate: new document opened from iCloud");
            }];
        }];
    }
}

- (void)queryDidFinishGathering:(NSNotification *)notification {

    // (3) if Query is finished, this will send the result (i.e. either it found our text.dat or it didn't) to the next function

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    [self loadData:query];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    _query = nil; // we're done with it
}

-(void)loadDocument {

    // (2) iCloud query: Looks if there exists a file called text.txt in the cloud

    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
    _query = query;
    //SCOPE
    [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
    //PREDICATE
    NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, @"text.txt"];
    [query setPredicate:pred];
    //FINISHED?
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
    [query startQuery];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"AppDelegate: app did finish launching");
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil] autorelease];
    } else {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil] autorelease];
    }

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    // (1) iCloud: init

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (ubiq) {
        NSLog(@"AppDelegate: iCloud access!");
        [self loadDocument];
    } else {
        NSLog(@"AppDelegate: No iCloud access (either you are using simulator or, if you are on your phone, you should check settings");
    }


    return YES;
}

@end

UIDocument

//  MyTextDocument.h
//  iCloudText

#import <Foundation/Foundation.h>
#import "ViewController.h"

@interface MyTextDocument : UIDocument {

    NSString *documentText;
    id delegate;

}

@property (nonatomic, retain) NSString *documentText;
@property (nonatomic, assign) id delegate;

@end

//  MyTextDocument.m
//  iCloudText

#import "MyTextDocument.h"
#import "ViewController.h"

@implementation MyTextDocument

@synthesize documentText = _text;
@synthesize delegate = _delegate;

// ** READING **

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError
{
    NSLog(@"UIDocument: loadFromContents: state = %d, typeName=%@", self.documentState, typeName);

    if ([contents length] > 0) {
        self.documentText = [[NSString alloc] initWithBytes:[contents bytes] length:[contents length] encoding:NSUTF8StringEncoding];
    }
    else {
        self.documentText = @"";
    }

    NSLog(@"UIDocument: Loaded the following text from the cloud: %@", self.documentText);


    // update textView in delegate...
    if ([_delegate respondsToSelector:@selector(noteDocumentContentsUpdated:)]) {
        [_delegate noteDocumentContentsUpdated:self];
    }

    return YES;

}

// ** WRITING **

-(id)contentsForType:(NSString *)typeName error:(NSError **)outError
{
    if ([self.documentText length] == 0) {
        self.documentText = @"New Note";
    }

    NSLog(@"UIDocument: Will save the following text in the cloud: %@", self.documentText);

    return [NSData dataWithBytes:[self.documentText UTF8String] length:[self.documentText length]];
}
@end

GÖRÜNÜM DENETLEYİCİSİ

//
//  ViewController.h
//  iCloudText

#import <UIKit/UIKit.h>

@class MyTextDocument;

@interface ViewController : UIViewController <UITextViewDelegate> {

    IBOutlet UITextView *textView;

}

@property (nonatomic, retain) UITextView *textView;
@property (strong, nonatomic) MyTextDocument *document;

-(void)noteDocumentContentsUpdated:(MyTextDocument *)noteDocument;

@end

//  ViewController.m
//  iCloudText

#import "ViewController.h"
#import "MyTextDocument.h"

@implementation ViewController

@synthesize textView = _textView;
@synthesize document = _document;

-(IBAction)dismissKeyboard:(id)sender {

    [_textView resignFirstResponder];

}

-(void)noteDocumentContentsUpdated:(MyTextDocument *)noteDocument
{
    NSLog(@"VC: noteDocumentsUpdated");
    _textView.text = noteDocument.documentText;
}

-(void)textViewDidChange:(UITextView *)theTextView {

     NSLog(@"VC: textViewDidChange");
    _document.documentText = theTextView.text;
    [_document updateChangeCount:UIDocumentChangeDone];

}

4
Bunu birkaç soruya bölmeyi gerçekten öneririm. Burada gömülü birkaç farklı soru görüyorum ve bunları buradaki metnin duvarında seçmek zor. Bu soruyu, iCloud'u etkinleştirmemiş kişiler için ne yapılacağını sormaya geri döndürürdüm ve diğerlerini (örnek kodunuzun yalnızca ilgili kısımlarıyla) ayrı sorulara bölerim. İyi sorular, ama ikiye bölünmeleri gerektiğini düşünüyorum.
Brad Larson

@BradLarson Yorumunuz için teşekkürler. Soru (lar) birbirine biraz karışmışsa özür dilerim, ancak ana sorunun (belirtmeye çalıştığım gibi) uygulama korumalı alanına karşı iCloud korumalı alan sorunu olduğunu düşünüyorum. Tam kodu (en kısa iCloud kod örneği, btw) sağladım, çünkü TÜM bağlamın neler olup bittiğini bilmek için hayati önem taşıdığını düşündüm ... Ancak başka bir soru açıp bu soruya geri bağlayabilirim. büyük resmi görün.
n.evermind

@BradLarson Tamam, burada yeni bir soru açtım: stackoverflow.com/questions/7798555/…
n.evermind

Hala Core Data ve iCloud ile ilgilenmeye çalışanlar için
Duncan Groenewald

Kapatılmaması gereken bu aslında iCloud'da gördüğüm daha yapıcı gönderilerden biri ..
Andrew Smith

Yanıtlar:


22

Dokümanları yeniden okudum ve görünüşe göre genel yaklaşımım yanlış. Dosyayı önce korumalı alanda oluşturmalı ve ardından buluta taşımalıyım. Başka bir deyişle, Apple her zaman aynı dosyanın üç sürümüne sahip olmam gerektiğini öneriyor gibi görünüyor: biri uygulamamın dizininde, biri aygıtımın iCloud iblis dizininde (çevrimdışıyken de erişilebilir) ve biri Bulut:

Uygulamalar, yerel dosyalar ve dizinler için yaptıklarıyla iCloud'daki dosyaları ve dizinleri yönetmek için aynı teknolojileri kullanır. İCloud'daki dosyalar ve dizinler hala yalnızca dosya ve dizinlerdir. Bunları açabilir, oluşturabilir, taşıyabilir, kopyalayabilir, okuyup yazabilir, silebilir veya yapmak isteyebileceğiniz diğer işlemlerden herhangi birini yapabilirsiniz. Yerel dosyalar ve dizinler ile iCloud dosyaları ve dizinleri arasındaki tek fark, onlara erişmek için kullandığınız URL'dir. URL'lerin uygulamanızın korumalı alanına göre olması yerine, iCloud dosyalarının ve dizinlerinin URL'leri, ilgili iCloud kapsayıcı dizinine bağlıdır.

Bir dosyayı veya dizini iCloud'a taşımak için:

Dosyayı veya dizini uygulama sanal alanınızda yerel olarak oluşturun. Kullanımdayken, dosya veya dizin, UIDocument nesnesi gibi bir dosya sunucusu tarafından yönetilmelidir.

Öğeyi depolamak istediğiniz iCloud kapsayıcı dizinin URL'sini almak için URLForUbiquityContainerIdentifier: yöntemini kullanın. Öğenin iCloud'daki konumunu belirten yeni bir URL oluşturmak için kapsayıcı dizini URL'sini kullanın. Öğeyi iCloud'a taşımak için setUbiquitous: itemAtURL: destinationURL: error: NSFileManager yöntemini çağırın. Bu yöntemi asla uygulamanızın ana iş parçacığından çağırmayın; bunu yapmak ana iş parçacığınızı uzun süre engelleyebilir veya uygulamanızın kendi dosya sunucularından birinde kilitlenmeye neden olabilir. Bir dosyayı veya dizini iCloud'a taşıdığınızda, sistem bu öğeyi uygulamanızın sanal alanından özel bir yerel dizine kopyalar, böylece iCloud arka plan programı tarafından izlenebilir. Dosya artık korumalı alanınızda olmasa da, uygulamanız dosyaya yine de tam erişime sahiptir. Dosyanın bir kopyası geçerli aygıt için yerel olarak kalsa da, dosya başka aygıtlara dağıtılabilmesi için iCloud'a da gönderilir. İCloud arka plan programı, yerel kopyaların aynı olduğundan emin olmak için tüm işi halleder. Yani uygulamanızın perspektifinden, dosya yalnızca iCloud'da.

İCloud'daki bir dosya veya dizinde yaptığınız tüm değişiklikler, bir dosya koordinatörü nesnesi kullanılarak yapılmalıdır. Bu değişiklikler, öğenin taşınması, silinmesi, kopyalanması veya yeniden adlandırılmasını içerir. Dosya koordinatörü, iCloud arka plan programının dosyayı veya dizini aynı anda değiştirmemesini ve yaptığınız değişikliklerden diğer ilgili tarafların haberdar edilmesini sağlar.

Bununla birlikte, setUbiquitous ile ilgili belgelerde biraz daha derine inerseniz, şunları bulacaksınız:

Bir dosyayı mevcut konumundan iCloud'a taşımak için bu yöntemi kullanın. Bir uygulamanın sanal alanında bulunan dosyalar için bu, dosyanın sanal alan dizininden fiziksel olarak kaldırılmasını içerir . (Sistem, uygulamanızın sanal alan ayrıcalıklarını iCloud'a taşıdığı dosyalara erişim sağlamak için genişletir.) Bu yöntemi, dosyaları iCloud'un dışına ve yerel bir dizine geri taşımak için de kullanabilirsiniz.

Bu, bir dosyanın / dizinin yerel sanal alandan silindiği ve buluta taşındığı anlamına gelir.


1
url bağlantısı bozuk ...
ngb

5

Örneğinizi kullanıyorum ve iCloud'un temellerini kavramama yardımcı olduğu için seviyorum. Şimdi, söyleyebildiğim kadarıyla bu vakaları oluşturan iCloud'u kullanan veya kullanmayan yerel olarak depolanan içerikle uygulamanın mevcut kullanıcılarını desteklemek zorunda olan kendi uygulamam için sorunuzla uğraşıyorum:

Vakalar:

  1. Yeni kullanıcı
    • icloud'a sahip - icloud'da belgeler oluştur
    • icloud yok - belgeleri yerel olarak oluşturun
  2. Mevcut kullanıcı
    • icloud var
      • yeni eklendi - yerel dokümanları icloud'a taşı
      • sadece eklenmedi - belgeleri icloud'a aç / kaydet
    • icloud yok
      • yeni kaldırıldı - eski icloud belgelerini yerel olarak taşıyın
      • sadece kaldırılmaz - dokümanları yerel olarak açın / kaydedin

Birisi iCloud'u kaldırırsa - her yerde bulunan URL çağrıları sıfıra dönmez mi? Bu durumda, dokümanları yerel depolamaya nasıl geri taşıyabilirim? Şimdilik bir kullanıcı tercihi oluşturacağım ama biraz geçici bir çözüm gibi görünüyor.

Burada bariz bir şeyi kaçırdığımı hissediyorum, bu yüzden eğer biri görebiliyorsa, lütfen haber verin.


Bu vakaları ele alan bir sınıf olup olmadığını merak ettiğimi eklemeliyim, bu yüzden sadece onu kullanıyorum ve nereye kaydedeceğimi düşünmek zorunda kalmam.
earnshavian

Bir şeyin yerel korumalı alana mı yoksa buluta mı yerleştirilmesi gerektiğini belirlemek için bazı örnek kodlar veren developer.apple.com/library/ios/#documentation/DataManagement/… sayfasına bir göz atın .
n.evermind

Bunun için teşekkürler. Bu dokümanı görmüştüm ama iCloud görevimde daha önce sunduğu kodu unutmuştum. Örneğinizi yerel ve uzaktan destekleyecek şekilde uyarlamaya çalışacağım. Her yerde bulunan URL'yi kaybettiğimiz için iCloud'u devre dışı bırakan kullanıcıyı nasıl idare edeceğimiz konusunda hâlâ net değilim, ancak bir çatlak ve bir güncelleme paylaşacağım.
winshavian

1
Yani bir bakıma, bulut için URL'leri ve yerel sanal alan için PATH'leri kullanmak zorunda olmamız biraz aptalca. İCloud'un bizim için her şeyi halledebilmesi güzel olurdu ... ama bu şekilde, açtığımız her dosya için temelde iki farklı yöntem kodlamamız gerekiyor.
n.evermind

Yazınızı yeniden okudum. Şimdi kullanıcının tercihini (yani kullanıcı iCloud'u kullanmak istiyor / istemiyor) NSUserDefaults'a kaydediyorum. Apple'ın da önerdiği budur. İCloud'un erişilebilir olup olmadığını her zaman kontrol ederim. Erişilebilir değilse, kullanıcılara bunu açmalarını söylüyorum - ancak yalnızca uygulamaya onu kullanmak istemediklerini açıkça söylememişlerse. Aksi takdirde iCloud'u kullanmak istemeyenler için can sıkıcı oluyor. İCloud'un etkinleştirilip etkinleştirilmediğini belirledikten sonra, ya her yerde bulunan URL yolunu izleyeceğim ve UIDocument kullanacağım VEYA dosyaları eski güzel günlerde olduğu gibi sandbox'tan açacağım.
n.evermind

4

Kullanıcıların iOS 5.0 öncesi cihazlar arasında metin paylaşabilmesini istiyorsanız, iCloud'dan önce herkesin yapması gerekeni yapmanız ve bilgileri kendi sunucunuza taşımanız gerekecektir.

Gerçekten ihtiyacınız olan tek şey, uygulamanızın metin dosyalarını kaydetmesine ve bunları bir kullanıcı hesabıyla ilişkilendirmesine izin veren bir sunucudur.

Kullanıcıların bir hesap oluşturmasına ihtiyacınız olacak ve yeni bilgileri bir cihazda kendi 'bulutunuza' taşıma sürecini kendiniz yönetmeniz gerekecek.

Kullanıcılar, diğer cihazlarda aynı hesapla kayıt olacak ve başka bir cihazın verileri kendi bulutunuza taşıdığını tespit etmeye özen göstermeniz ve mevcut cihazı yeni bilgilerle güncellemeniz gerekir.

Açıkçası, iOS 5.0 aygıtları için, muhtemelen kendi bulutunuzdaki iOS 5.0 öncesi aygıtlar için değişen dosyaları algılamak ve ayrıca iCloud ile konuşabilmek isteyeceksiniz.


Teşekkürler. Diğer bir deyişle, iOS 5 öncesi cihazları desteklemek istemiyorsam, sadece UIDocument ile gidiyorum ve uygulamamın sanal alanındaki doc dizininin içeriğini unutuyorum.
n.evermind

Anladığım kadarıyla, sandbox'ta hala UIDocument'in iCloud ile aracılık etmesine yardımcı olacak bir belgeniz olacak, ancak ona ne zaman erişebileceğiniz size söylenecek ... Hala alıyorum bu şeyleri kendim halletmek için!
Jonathan Watmough

3

Bir iOS5 / notIOS5 sorunu kadar bir iCloud / notICloud sorunu ile mücadele ediyormuşsunuz gibi görünmüyor.

Dağıtım hedefiniz iOS5 ise, her zaman UIDocument yapısını kullanın. Her yerde bulunuyorsa, NSMetaDataQuery'niz onu bulutta bulacaktır; değilse cihazda bulacaktır.

Öte yandan, uygulamanıza 5.0 öncesi erişim sağlamak istiyorsanız, çalışan iOS'un 5.0 veya üstü olup olmadığını görmek için koşullu olarak kontrol etmeniz gerekecektir. Daha sonra UIDocument kullanılıyorsa; değilse, verileri eski şekilde okuyun / yazın.

Benim yaklaşımım, iOS5'i kontrol eden koşullu bir saveData yöntemi yazmaktı. Varsa, değişiklik sayısını güncellerim (veya bir geri alma yöneticisi kullanırım). Sizin durumunuzda textViewDidChange bu yöntemi çağırır. Değilse, eski yöntemle diske kaydeder. Yükleme sırasında bunun tersi olur.


1

"İCloud'daki dosyalara, uygulamanızın korumalı alanındaki diğer tüm dosyalara yaptığınız gibi muamele edin." Bu, bir grup dosyayı sakladığınız Keynote ve Numbers gibi bir şey için geçerlidir ve iCloud'unuz varsa, sihirli bir şekilde senkronize etmeye başlarlar.

Ancak, iCloud benzeri işlevselliğe bağlı bir şey oluşturuyorsunuz. Bu ifadeyi tutamazsınız çünkü uygulamanız, herhangi bir şeyin olması gerektiği gibi çalışması için iCloud'un mevcut olmasına bağlıdır. Ya uygulamanızı kapatmanız ve "lütfen bunun çalışması için iCloud'u kurun" demeniz veya her zaman kullanabileceğiniz iCloud benzeri işlevselliği (kendinizin veya başkasının) çoğaltmanız gerekir.


Teşekkürler. Bu yüzden, iCloud işlevselliğini değiştiren insanlar için yalnızca iCloud uygulaması mı yoksa bir tür hibrit mi yapacağımı seçmem gerektiğini düşünüyorum. İCloud çok karmaşık olduğundan, o zaman yalnızca iCloud uygulamasına gitme eğilimindeyim. Teşekkürler.
n.evermind
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.