I have a direct Mac OS X-enabled application based on NSDocument in which I am trying to implement an iCloud document repository. I am building with 10.7 SDK.
I prepared my application for storing iCloud documents and included the necessary rights (AFAICT). The application builds, runs, and creates a local container. The document file is ubiquitous correctly (this took some time, but everything seems to work). I am using the NSFileCoordinator API as recommended by Apple. I am sure that I am using the correct UbiquityIdentifier as recommended by Apple (it is edited below tho).
I closely followed the Apple iCloud Document demo instructions in this WWDC 2011 video:
Session 107 Autosave and versions in the lion
My code looks almost identical to the code from this demo.
However, when I call my action to move the current document to the cloud, when I call the method -[NSFileManager setUbiquitous:itemAtURL:destinationURL:error:] I have problems with liveness . He never returns.
Here is the relevant code from my subclass of NSDocument . It is almost identical to the Apple WWDC demo code. Since this is an action, it is called in the main thread (as shown by the Apple demo code). Closing occurs to the end when the -setUbiquitous:itemAtURL:destinationURL:error: method is -setUbiquitous:itemAtURL:destinationURL:error: . I tried moving to the background thread, but it never returns anyway.
It seems that the semaphore is blocking, waiting for a signal that never arrives.
When I run this code in the debugger, my source and destination URLs look correct, so I'm sure they are calculated correctly, and I confirmed that the directories exist on the disk.
Am I doing something obviously wrong, which will cause -setUbiquitous not return?
- (IBAction)moveToOrFromCloud:(id)sender { NSURL *fileURL = [self fileURL]; if (!fileURL) return; NSString *bundleID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; NSString *appID = [NSString stringWithFormat:@"XXXXXXX.%@.macosx", bundleID]; BOOL makeUbiquitous = 1 == [sender tag]; NSURL *destURL = nil; NSFileManager *mgr = [NSFileManager defaultManager]; if (makeUbiquitous) { // get path to local ubiquity container Documents dir NSURL *dirURL = [[mgr URLForUbiquityContainerIdentifier:appID] URLByAppendingPathComponent:@"Documents"]; if (!dirURL) { NSLog(@"cannot find URLForUbiquityContainerIdentifier %@", appID); return; } // create it if necessary [mgr createDirectoryAtURL:dirURL withIntermediateDirectories:NO attributes:nil error:nil]; // ensure it exists BOOL exists, isDir; exists = [mgr fileExistsAtPath:[dirURL relativePath] isDirectory:&isDir]; if (!(exists && isDir)) { NSLog(@"can't create local icloud dir"); return; } // append this doc filename destURL = [dirURL URLByAppendingPathComponent:[fileURL lastPathComponent]]; } else { // get path to local Documents folder NSArray *dirs = [mgr URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; if (![dirs count]) return; // append this doc filename destURL = [[dirs objectAtIndex:0] URLByAppendingPathComponent:[fileURL lastPathComponent]]; } NSFileCoordinator *fc = [[[NSFileCoordinator alloc] initWithFilePresenter:self] autorelease]; [fc coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForMoving writingItemAtURL:destURL options:NSFileCoordinatorWritingForReplacing error:nil byAccessor:^(NSURL *fileURL, NSURL *destURL) { NSError *err = nil; if ([mgr setUbiquitous:makeUbiquitous itemAtURL:fileURL destinationURL:destURL error:&err]) { [self setFileURL:destURL]; [self setFileModificationDate:nil]; [fc itemAtURL:fileURL didMoveToURL:destURL]; } else { NSWindow *win = ... // get my window [self presentError:err modalForWindow:win delegate:nil didPresentSelector:nil contextInfo:NULL]; } }]; }