I'm struggling a bit with the idea of iCloud and posted a more general question here. My biggest problem is to decide whether I should stop putting the user's data in the good old documents folder which is found in the app's sandbox. To illustrate my problem:
The docs don't give an answer as far as I can see. Let's suppose I have an App which handles different txt files. Once I start my app, I simply check if any txt files are in the cloud like so:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"AppDelegate: app did finish launching");
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
// (1) iCloud: init
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq) {
NSLog(@"User has iCloud enabled! Let's get the txt files from the cloud.");
[self loadDocument];
} else {
NSLog(@"User doesn't have iCloud enabled. App is thus worthless.");
}
return YES;
}
I then have a method to check if there are any txt files in the cloud and if so, load them. If not, I simply create new txt files in the cloud.
This means that the app does not store any data in the documents folder. As far as I understand it, everything is either in the local iCloud storage of my device (which is also accessible if the user is OFFLINE) or in the cloud. So the text file exists in two places: on my device and the cloud.
So there is simply no need to store a third copy in my local documents folder, right? Or is this essential for some reason I have overlooked? In other words, for what should I use the local documents folder if I offer iCloud to my users? (And can I simply ignore those who won't sign up for iCloud?)
EDIT: Just to clarify, when I'm talking about the standard documents folder in the app's sandbox, I mean this one:
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
If you turn off iCloud on your iPhone only, all of the photos in your iPhone will remain. You can also access your photos on the connected devices or on iCloud. But, a newly taken image will no longer be saved on iCloud.
They disable iCloud Photos on their Apple devices and retain images and videos variously based on storage. This unlinks their device-based Photos libraries from iCloud synchronization among them, and between them and iCloud.com. They go to iCloud.com and delete images.
On iPhone, go to the Activity app , then tap Sharing. Tap a person you share with, click their name, then select either Remove Friend or Hide my Activity. You can also choose to share information with others using third-party apps.
You can use Find My iPhone on iCloud.com to temporarily remove a device from the Devices list or turn off Activation Lock on a device you already gave away or sold.
Perhaps I'm a bit slow, by re-reading the docs for the 4th or 5th time, I came across this which suggests that you should always create your files in the sandbox and then move them to the cloud. So in a way, Apple suggests to have 3 versions of the same file at all times:
Apps use the same technologies to manage files and directories in iCloud that they do for local files and directories. Files and directories in iCloud are still just files and directories. You can open them, create them, move them, copy them, read and write from them, delete them, or any of the other operations you might want to do. The only differences between local files and directories and iCloud files and directories is the URL you use to access them. Instead of URLs being relative to your app’s sandbox, URLs for iCloud files and directories are relative to the corresponding iCloud container directory.
To move a file or directory to iCloud:
Create the file or directory locally in your app sandbox. While in use, the file or directory must be managed by a file presenter, such as a UIDocument object.
Use the URLForUbiquityContainerIdentifier: method to retrieve a URL for the iCloud container directory in which you want to store the item. Use the container directory URL to build a new URL that specifies the item’s location in iCloud. Call the setUbiquitous:itemAtURL:destinationURL:error: method of NSFileManager to move the item to iCloud. Never call this method from your app’s main thread; doing so could block your main thread for an extended period of time or cause a deadlock with one of your app’s own file presenters. When you move a file or directory to iCloud, the system copies that item out of your app sandbox and into a private local directory so that it can be monitored by the iCloud daemon. Even though the file is no longer in your sandbox, your app still has full access to it. Although a copy of the file remains local to the current device, the file is also sent to iCloud so that it can be distributed to other devices. The iCloud daemon handles all of the work of making sure that the local copies are the same. So from the perspective of your app, the file just is in iCloud.
All changes you make to a file or directory in iCloud must be made using a file coordinator object. These changes include moving, deleting, copying, or renaming the item. The file coordinator ensures that the iCloud daemon does not change the file or directory at the same time and ensures that other interested parties are notified of the changes you make.
See here.
There is no reason to store documents both in local storage as well as in iCloud. However, you should give users the option of turning iCloud storage off. With iCloud storage off, you should only look for files in local storage (as with pre-iOS5 apps). The best thing is to try to isolate the part of your code that needs to know where documents are stored, and have it test whether or not iCloud is available and enabled and have that piece of code return the URL where documents should be stored.
Update: If you want to diverge for iOS5 vs. iOS4, you just need to test if the iOS5 features are there. There are several ways that you can do this. One way is to check:
if ([UIDocument class] == nil)
On iOS4 this will be true, and on iOS5 this will be false. I don't know what kind of datastructures you have for your files, but one thing you could do is create a wrapper around UIDocument. Inside this wrapper class, you could have instance variables for a UIDocument structure as well as for fields you would need in IOS4 (such as the path to the file). When you instantiate your class, test whether iCloud is enabled and if UIDocument is available, and if so, use it and set the field. Otherwise, set the other fields and leave the UIDocument field to be nil. When you need to do operations on your "file", test if the UIDocument field is nil, and if it is do it the "old" way. Otherwise, just pass on the request to the UIDocument object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With