Apple iCloud implementation in Mac apps

I know that iOS has an API for integrating iCloud for apps. Can i integrate iCloud in Mac apps? Will the implementation be different for Mac apps for iCloud integration? If so, are there any tutorials or reference sites?

+6
source share
2 answers

Yes. iCloud is available on Mac.
But Apple's documentation on this topic is still not very complete. The only official resources I could find where the WWDC 2011 session 107 videos and some notes in "What's New in Mac OS X"

When Leo and iCloud were still under the NDA, I posted my results to Apple devforums.
This is an edited version of this post :

I am using a modified version of the WWDC 2011 Session 107 code. (Transcribed from the video) I had to remove the manual copy of NSFileCoordinator to make the sample work (he mentions that the coordinator “may not be needed in the future”):

- (IBAction)moveToOrFromCloud:(id)sender { NSFileManager* fm = [NSFileManager defaultManager]; NSURL* fileURL = [[self document] fileURL]; BOOL shouldMakeUbiquitous = [sender tag] == 1; NSURL* destinationURL; if(shouldMakeUbiquitous) { NSURL* rootURL = [fm URLForUbiquityContainerIdentifier:@"app.example"]; NSURL* directoryURL = [rootURL URLByAppendingPathComponent:@"Documents"]; [fm createDirectoryAtURL:directoryURL withIntermediateDirectories:NO attributes:nil error:NULL]; destinationURL = [directoryURL URLByAppendingPathComponent:[fileURL lastPathComponent]]; } else { destinationURL = [[[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:[fileURL lastPathComponent]]; } NSError* error; if(![fm setUbiquitous:shouldMakeUbiquitous itemAtURL:fileURL destinationURL:destinationURL error:&error]) { [[self document] presentError:error modalForWindow:[[self document] windowForSheet] delegate:nil didPresentSelector:NULL contextInfo:NULL]; } else { [[self document] setFileURL:destinationURL]; [[self document] setFileModificationDate:nil]; } } 

The above IBAction is connected to NSMenuItem, which checks if the document is already in iCloud or if it should be loaded:

 - (BOOL)validateMenuItem:(NSMenuItem*)item { SEL action = [item action]; if (action == @selector(moveToOrFromCloud:)) { BOOL isUbiquitous = [[NSFileManager defaultManager] isUbiquitousItemAtURL:[[self document] fileURL]]; [item setTitle:isUbiquitous ? @"Remove from Cloud": "Move to Cloud"]; [item setTag:isUbiquitous?0:1]; return [self.document fileURL] != nil; } return YES; } 

Checklist for tasks without code required for the iCloud document repository to work:

  • Check if iCloud support is enabled in the Developer Certificate Utility.
  • Create the ubiquity container identifier in the Developer Certificate Utility.
  • The Ubiquity container identifier begins with the identifier of your team / individual identifier (see the account tab in the participant’s center).
  • Enabling Rights in Xcode
  • Add your ubiquity container identifier to the rights file (as described here, “Request iCloud Storage Permissions.”)
  • My Plist package id must match the ubiquity container id (except for the command id).
  • I could not add suffixes (for example, "app.example.osx", "app.example.ipad", ... as suggested in the document above)
  • Create a training profile
  • Make sure the profile is installed on your development computer and displayed in Xcode and system settings
  • Enable code signing in your application settings
+4
source

There is an Apple document that is mandatory for all aspects of http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/iCloud/iCloud.html

One major issue with the code presented here is that it does not have a command in the identifier specified for the URLForUbiquityContainerIdentifier, even if it is mentioned in the checklist, leaving it completely populated from the rights, it seems like the best aproach.

Personally, the only changes I had to make to get iCloud in my application:

  • check the "use iCloud" checkbox on the developer's website for my app ID.
  • load restored position for this application id
  • check "enable rights" in xcode summary

That’s all, here’s probably a clearer code example (should work for both iOS and OSX):

 NSURL *url = [self getiCloudURLFor:@"foo.bar" containerID:nil]; //leaving nil so it is auto filled from entitlements if (url) { NSError *error; if (![[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:url error:&error]) { NSLog(@"Error downloading/syncing %@ (%@)",[url path],[error description]); }else{ NSLog(@"Started downloading/syncing %@",[url path]); } } NSArray *conflicts = [NSFileVersion unresolvedConflictVersionsOfItemAtURL:url]; for (NSFileVersion *conflict in conflicts) { NSLog(@"Conflicting %@ at %@ by %@ from %@",[url path],[conflict URL],[conflict localizedNameOfSavingComputer],[conflict modificationDate]); } - (NSURL*)getiCloudURLFor:(NSString*)fileName containerID:(NSString*)containerID { NSFileManager *fm = [NSFileManager defaultManager]; NSURL *rootURL = [fm URLForUbiquityContainerIdentifier:containerID]; if (rootURL) { NSURL *directoryURL = [rootURL URLByAppendingPathComponent:@"Documents"]; if (![fm fileExistsAtPath:[directoryURL path]]) [fm createDirectoryAtURL:directoryURL withIntermediateDirectories:NO attributes:nil error:NULL]; NSURL *cloudURL = [directoryURL URLByAppendingPathComponent:fileName]; if (![fm isUbiquitousItemAtURL:cloudURL]) [self makeUbiquitousItemAtURL:cloudURL];//this only runs once per filename when it is first added to iCloud return cloudURL; }else{ return [[[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:fileName]; //no cloud } return nil; } - (void)makeUbiquitousItemAtURL:(NSURL*)cloudURL { NSFileManager *fm = [NSFileManager defaultManager]; NSURL *localURL = [[[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:[cloudURL lastPathComponent]]; if (![fm fileExistsAtPath:[localURL path]]) [fm createFileAtPath:[localURL path] contents:nil attributes:nil]; NSError *error; if(![fm setUbiquitous:YES itemAtURL:localURL destinationURL:cloudURL error:&error]) { NSLog(@"Error making %@ ubiquituous at %@ (%@)",[localURL path],[cloudURL path],[error description]); }else{ NSLog(@"Made %@ ubiquituous at %@",[localURL lastPathComponent],[cloudURL path]); } } 
+1
source

Source: https://habr.com/ru/post/903046/


All Articles