iCloud-Grundlagen und Codebeispiel [geschlossen]

85

Als Anfänger habe ich Probleme mit iCloud. Es gibt einige Beispiele, aber sie sind normalerweise ziemlich detailliert (im Entwicklerforum gibt es eines für iCloud und CoreData, das riesig ist). Die Apple-Dokumente sind in Ordnung, aber ich kann das große Ganze immer noch nicht sehen. Bitte nehmen Sie mit, einige dieser Fragen sind recht grundlegend, aber möglicherweise leicht zu beantworten.

Kontext: Ich habe eine sehr einfache iCloud-App (vollständiger Beispielcode unten). Dem Benutzer wird nur eine UITextView angezeigt, und seine Eingabe wird in einer Datei namens text.txt gespeichert.

Geben Sie hier die Bildbeschreibung ein

Die txt-Datei wird in die Cloud verschoben und allen Geräten zur Verfügung gestellt. Funktioniert perfekt, aber:

Hauptproblem: Was ist mit Benutzern, die iCloud nicht verwenden?

Wenn ich meine App starte (siehe Code unten), überprüfe ich, ob der Benutzer iCloud aktiviert hat. Wenn iCloud aktiviert ist, ist alles in Ordnung. Die App geht voran und sucht in der Cloud nach text.txt. Wenn es gefunden wird, wird es geladen und dem Benutzer angezeigt. Wenn text.txt nicht in der Cloud gefunden wird, wird einfach eine neue text.txt erstellt und dem Benutzer angezeigt.

Wenn der Benutzer iCloud nicht aktiviert hat, geschieht nichts. Wie mache ich es möglich, dass Nicht-iCloud-Benutzer weiterhin mit meiner Text-App arbeiten können? Oder ignoriere ich sie einfach? Muss ich separate Funktionen für Nicht-iCloud-Benutzer schreiben? Dh Funktionen, bei denen ich einfach eine text.txt aus dem Dokumentenordner lade?

Apple schreibt :

Behandeln Sie Dateien in iCloud genauso wie alle anderen Dateien in Ihrer App-Sandbox.

In meinem Fall gibt es jedoch keine "normale" App-Sandbox mehr. Es ist in der Cloud. Oder lade ich meine text.txt immer zuerst von der Festplatte und überprüfe dann mit iCloud, ob etwas aktueller ist?

Zugehöriges Problem: Dateistruktur - Sandbox vs. Cloud

Vielleicht ist mein Hauptproblem ein grundlegendes Missverständnis darüber, wie iCloud funktionieren soll. Wenn ich eine neue Instanz eines UIDocument erstelle, muss ich zwei Methoden überschreiben. Zuerst - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outErrorum Dateien aus der Cloud und dann -(id)contentsForType:(NSString *)typeName error:(NSError **)outErrorum Dateien in die Cloud zu bekommen.

Muss ich separate Funktionen integrieren, die auch eine lokale Kopie von text.txt in meiner Sandbox speichern? Funktioniert dies für Nicht-iCloud-Benutzer? Soweit ich weiß, wird iCloud automatisch eine lokale Kopie von text.txt speichern. Ich sollte also nichts in der "alten" Sandbox meiner App speichern müssen (dh wie früher in der Zeit vor iCloud). Im Moment ist mein Sandkasten völlig leer, aber ich weiß nicht, ob dies korrekt ist. Soll ich dort eine weitere Kopie von text.txt aufbewahren? Das fühlt sich an, als würde meine Datenstruktur überladen ... da sich eine text.txt in der Cloud befindet, eine in der iCloud-Sandbox auf meinem Gerät (die auch dann funktioniert, wenn ich offline bin) und eine dritte in der guten alten Sandbox von meine App...


MEIN CODE: Ein einfacher iCloud-Beispielcode

Dies basiert lose auf einem Beispiel, das ich im Entwicklerforum und im WWDC-Sitzungsvideo gefunden habe. Ich habe es auf das Nötigste reduziert. Ich bin mir nicht sicher, ob meine MVC-Struktur gut ist. Das Modell befindet sich im AppDelegate, was nicht ideal ist. Vorschläge zur Verbesserung sind willkommen.


EDIT: Ich habe versucht, die Hauptfrage zu extrahieren und sie [hier] gepostet. 4


ÜBERBLICK:

Überblick

Das wichtigste Bit, das die text.txt aus der Cloud lädt:

//  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

Das 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

DER VIEWCONTROLLER

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

}
keine Ursache
quelle
4
Ich würde wirklich vorschlagen, dies in ein paar Fragen aufzuteilen. Ich sehe hier ein paar verschiedene Fragen, und es ist schwierig, sie in der Textwand herauszusuchen, die Sie hier haben. Ich würde diese Frage wieder auf die Frage zurückführen, was für Personen zu tun ist, für die iCloud nicht aktiviert ist, und die anderen (nur mit den relevanten Teilen Ihres Beispielcodes) in separate Fragen aufteilen. Das sind gute Fragen, aber ich denke, sie sollten aufgeteilt werden.
Brad Larson
@BradLarson Danke für deinen Kommentar. Es tut mir leid, wenn die Frage (n) etwas durcheinander sind, aber ich denke, die Hauptfrage (wie ich versucht habe anzuzeigen) ist das Problem zwischen App-Sandbox und iCloud-Sandbox. Ich habe den vollständigen Code bereitgestellt (übrigens das kürzeste iCloud-Codebeispiel), da ich dachte, dass der GESAMTE Kontext wichtig ist, um zu wissen, was los ist ... Aber ich könnte einfach eine andere Frage öffnen und sie mit dieser Frage verknüpfen Holen Sie sich das größere Bild.
n.evermind
@BradLarson OK, ich habe hier eine neue Frage gestellt: stackoverflow.com/questions/7798555/…
n.evermind
Für diejenigen, die immer noch versuchen, Core Data und iCloud in den Griff zu bekommen, versuchen Sie diesen Link ossh.com.au/design-and-technology/software-development/…
Duncan Groenewald
Sollte nicht geschlossen werden, ist dies tatsächlich einer der konstruktiveren Beiträge, die ich auf iCloud gesehen habe.
Andrew Smith

Antworten:

22

Ich habe gerade die Dokumente erneut gelesen und es scheint, dass mein allgemeiner Ansatz falsch ist. Ich sollte zuerst die Datei in der Sandbox erstellen und sie dann in die Cloud verschieben. Mit anderen Worten, Apple scheint vorzuschlagen, dass ich immer drei Versionen derselben Datei haben sollte: eine im Verzeichnis meiner App, eine im iCloud-Dämonenverzeichnis meines Geräts (auf das auch offline zugegriffen werden kann) und eine in die Wolke:

Apps verwenden zum Verwalten von Dateien und Verzeichnissen in iCloud dieselben Technologien wie für lokale Dateien und Verzeichnisse. Dateien und Verzeichnisse in iCloud sind immer noch nur Dateien und Verzeichnisse. Sie können sie öffnen, erstellen, verschieben, kopieren, lesen und schreiben, löschen oder andere Vorgänge ausführen, die Sie möglicherweise ausführen möchten. Der einzige Unterschied zwischen lokalen Dateien und Verzeichnissen und iCloud-Dateien und -Verzeichnissen besteht in der URL, über die Sie darauf zugreifen. Anstatt dass URLs relativ zur Sandbox Ihrer App sind, beziehen sich URLs für iCloud-Dateien und -Verzeichnisse auf das entsprechende iCloud-Containerverzeichnis.

So verschieben Sie eine Datei oder ein Verzeichnis nach iCloud:

Erstellen Sie die Datei oder das Verzeichnis lokal in Ihrer App-Sandbox. Während der Verwendung muss die Datei oder das Verzeichnis von einem Dateipräsentator verwaltet werden, z. B. einem UIDocument-Objekt.

Verwenden Sie die Methode URLForUbiquityContainerIdentifier:, um eine URL für das iCloud-Containerverzeichnis abzurufen, in dem Sie das Element speichern möchten. Verwenden Sie die URL des Containerverzeichnisses, um eine neue URL zu erstellen, die den Speicherort des Elements in iCloud angibt. Rufen Sie die Methode setUbiquitous: itemAtURL: destinationURL: error: von NSFileManager auf, um das Element in iCloud zu verschieben. Rufen Sie diese Methode niemals im Hauptthread Ihrer App auf. Dies könnte Ihren Hauptthread für einen längeren Zeitraum blockieren oder einen Deadlock bei einem der eigenen Dateipräsentatoren Ihrer App verursachen. Wenn Sie eine Datei oder ein Verzeichnis nach iCloud verschieben, kopiert das System dieses Element aus Ihrer App-Sandbox in ein privates lokales Verzeichnis, damit es vom iCloud-Dämon überwacht werden kann. Auch wenn sich die Datei nicht mehr in Ihrer Sandbox befindet, hat Ihre App weiterhin vollen Zugriff darauf. Obwohl eine Kopie der Datei lokal auf dem aktuellen Gerät bleibt, wird die Datei auch an iCloud gesendet, damit sie an andere Geräte verteilt werden kann. Der iCloud-Daemon übernimmt die gesamte Arbeit, um sicherzustellen, dass die lokalen Kopien identisch sind. Aus Sicht Ihrer App befindet sich die Datei also nur in iCloud.

Alle Änderungen, die Sie an einer Datei oder einem Verzeichnis in iCloud vornehmen, müssen mithilfe eines Dateikoordinatorobjekts vorgenommen werden. Diese Änderungen umfassen das Verschieben, Löschen, Kopieren oder Umbenennen des Elements. Der Dateikoordinator stellt sicher, dass der iCloud-Dämon die Datei oder das Verzeichnis nicht gleichzeitig ändert, und stellt sicher, dass andere interessierte Parteien über die von Ihnen vorgenommenen Änderungen informiert werden.

Wenn Sie sich jedoch etwas eingehender mit den Dokumenten zu setUbiquitous befassen, werden Sie Folgendes feststellen:

Verwenden Sie diese Methode, um eine Datei von ihrem aktuellen Speicherort in iCloud zu verschieben. Bei Dateien in der Sandbox einer Anwendung wird die Datei physisch aus dem Sandbox-Verzeichnis entfernt . (Das System erweitert die Sandbox-Berechtigungen Ihrer Anwendung, um Zugriff auf Dateien zu erhalten, die in iCloud verschoben werden.) Mit dieser Methode können Sie Dateien auch aus iCloud in ein lokales Verzeichnis verschieben.

Dies scheint also zu bedeuten, dass eine Datei / ein Verzeichnis aus der lokalen Sandbox gelöscht und in die Cloud verschoben wird.

keine Ursache
quelle
1
URL-Link ist defekt ...
ngb
5

Ich habe Ihr Beispiel verwendet und es gefällt mir, um die Grundlagen von iCloud zu verstehen. Jetzt ringe ich mit Ihrer Frage nach meiner eigenen App, die bestehende Benutzer der App mit lokal gespeicherten Inhalten unterstützen muss, die iCloud verwenden oder nicht, um diese Fälle zu erstellen, soweit ich das beurteilen kann:

Fälle:

  1. Neuer Benutzer
    • has icloud - Dokumente in icloud erstellen
    • no icloud - Dokumente lokal erstellen
  2. Existierender Benutzer
    • hat icloud
      • gerade hinzugefügt - migrieren Sie lokale Dokumente zu icloud
      • nicht nur hinzugefügt - Dokumente in icloud öffnen / speichern
    • keine icloud
      • gerade entfernt - migrieren Sie frühere icloud-Dokumente zu lokal
      • nicht nur entfernt - Dokumente öffnen / speichern

Wenn jemand iCloud entfernt - würden die Aufrufe der allgegenwärtigen URL nicht Null zurückgeben? Wenn dies der Fall ist, wie migriere ich die Dokumente zurück in den lokalen Speicher? Ich werde vorerst eine Benutzereinstellung erstellen, scheint aber eine Problemumgehung zu sein.

Ich habe das Gefühl, dass mir hier etwas Offensichtliches fehlt. Wenn jemand es sehen kann, melden Sie sich bitte.

Earnshavian
quelle
Ich sollte hinzufügen, dass ich mich frage, ob es eine Klasse gibt, die diese Fälle behandelt, also benutze ich das einfach und muss mir keine Gedanken darüber machen, wo ich es speichern soll.
Earnshavian
Schauen Sie sich developer.apple.com/library/ios/#documentation/DataManagement/… an, das einen Beispielcode enthält, um zu bestimmen, ob etwas in die lokale Sandbox oder in die Cloud gestellt werden soll.
n.evermind
Dank dafür. Ich hatte dieses Dokument gesehen, aber früher in meiner iCloud-Mission, also hatte ich den Code vergessen, den es bietet. Ich werde versuchen, Ihr Beispiel so anzupassen, dass es lokal und remote unterstützt. Ich bin mir immer noch nicht sicher, wie wir mit dem Benutzer umgehen, der iCloud deaktiviert, da wir die allgegenwärtige URL verlieren, aber ich werde einen Riss haben und ein Update teilen.
Earnshavian
1
In gewisser Weise ist es ein bisschen dumm, dass wir URLs für die Cloud und PATHs für die lokale Sandbox verwenden müssen. Es wäre schön, wenn iCloud alles für uns erledigen könnte ... aber auf diese Weise müssen wir grundsätzlich zwei verschiedene Methoden für jede Datei codieren, die wir öffnen.
n.evermind
Ich habe gerade Ihren Beitrag noch einmal gelesen. Ich speichere jetzt die Einstellungen des Benutzers (dh der Benutzer möchte / möchte iCloud nicht verwenden) in NSUserDefaults. Dies schlägt Apple ebenfalls vor. Ich überprüfe immer, ob iCloud zugänglich ist. Wenn es nicht zugänglich ist, fordere ich die Benutzer auf, es einzuschalten - aber nur, wenn sie der App nicht ausdrücklich mitgeteilt haben, dass sie es nicht verwenden möchten. Andernfalls wird es für diejenigen ärgerlich, die iCloud nicht verwenden möchten. Sobald ich festgestellt habe, ob iCloud aktiviert ist, folge ich entweder der allgegenwärtigen URL-Route und verwende UIDocument oder öffne einfach die Dateien aus der Sandbox wie früher.
n.evermind
4

Wenn Sie möchten, dass Benutzer Text zwischen Geräten vor iOS 5.0 austauschen können, müssen Sie das tun, was alle vor iCloud tun mussten, und Informationen auf Ihren eigenen Server verschieben.

Alles, was Sie wirklich brauchen, ist ein Server, auf dem Ihre App ihre Textdateien speichern und einem Benutzerkonto zuordnen kann.

Sie benötigen Benutzer, um ein Konto zu erstellen, und Sie müssen den Prozess selbst verwalten und neue Informationen auf einem Gerät in Ihre eigene "Cloud" verschieben.

Benutzer registrieren sich mit demselben Konto auf anderen Geräten, und Sie müssen sicherstellen, dass erkannt wird, wenn ein anderes Gerät Daten in Ihre eigene Cloud verschoben hat, und das aktuelle Gerät mit den neuen Informationen aktualisieren.

Für iOS 5.0-Geräte möchten Sie wahrscheinlich geänderte Dateien für Geräte vor iOS 5.0 in Ihrer eigenen Cloud erkennen und auch mit iCloud kommunizieren können.

Jonathan Watmough
quelle
Vielen Dank. Mit anderen Worten, wenn ich Geräte vor iOS 5 nicht unterstützen möchte, gehe ich einfach zu UIDocument und vergesse den Inhalt des doc-Verzeichnisses in der Sandbox meiner App.
n.evermind
Ziemlich genau, obwohl ich, soweit ich das beurteilen kann, immer noch ein Dokument in der Sandbox haben, das UIDocument Ihnen bei der Vermittlung mit iCloud hilft, aber Ihnen wird gesagt, wann Sie darauf zugreifen können ... Ich bekomme es immer noch dieses Zeug selbst in den Griff zu bekommen!
Jonathan Watmough
3

Es scheint nicht, dass Sie mit einem iCloud / notICloud-Problem zu kämpfen haben, sondern mit einem iOS5 / notIOS5-Problem.

Wenn Ihr Bereitstellungsziel iOS5 ist, verwenden Sie einfach immer die UIDocument-Struktur. Wenn es allgegenwärtig ist, findet es Ihre NSMetaDataQuery in der Cloud. Wenn nicht, wird es auf dem Gerät gefunden.

Wenn Sie andererseits Zugriff auf Ihre App vor 5.0 gewähren möchten, müssen Sie bedingt prüfen, ob das laufende iOS 5.0 oder höher ist. Wenn dies der Fall ist, verwenden Sie UIDocument. Wenn nicht, lesen / schreiben Sie die Daten auf die alte Weise.

Mein Ansatz war es, eine bedingte saveData-Methode zu schreiben, die nach iOS5 sucht. Wenn es existiert, aktualisiere ich die Änderungsanzahl (oder verwende einen Rückgängig-Manager). In Ihrem Fall würde textViewDidChange diese Methode aufrufen. Wenn nicht, wird auf die alte Weise auf der Festplatte gespeichert. Beim Laden passiert das Gegenteil.

Michael
quelle
1

Sie sind verwirrt von "Behandeln Sie Dateien in iCloud genauso wie alle anderen Dateien in Ihrer App-Sandbox." Dies gilt für so etwas wie Keynote und Numbers, bei denen Sie eine Reihe von Dateien aufbewahren. Wenn Sie über iCloud verfügen, werden diese auf magische Weise synchronisiert.

Sie erstellen jedoch etwas, das von der iCloud-ähnlichen Funktionalität abhängt. Sie können an dieser Aussage nicht festhalten, da Ihre App davon abhängt, dass iCloud vorhanden ist, damit alles so funktioniert, wie es soll. Sie müssen entweder Ihre App schließen und einfach "Bitte richten Sie iCloud ein, damit dies funktioniert" sagen oder iCloud-ähnliche Funktionen (Ihre eigenen oder die einer anderen Person) duplizieren, die Sie unabhängig davon immer verwenden können.

Jesper
quelle
Vielen Dank. Ich muss mich also wohl entscheiden, ob ich eine iCloud-App oder eine Art Hybrid für Leute mache, die die iCloud-Funktionalität deaktivieren. Da iCloud so komplex ist, tendiere ich dann dazu, nur eine iCloud-App zu verwenden. Vielen Dank.
n.evermind