How to sync NSDocument with Mac OSX on iPad / iPhone with iCloud

I saw an iCloud Document sample code for iOS and I used it to sync uidocument from iCloud and now I'm trying to sync iCloud with in a Mac OSX app that does not have UIDocument .

I tried changing the UIDocument to NSDocument , but all methods are synchronized with . I have not found any code examples or tutorials other than the documentation from , which is very confusing and poorly written.

For example, the method below, from a UIDocument on iOS does not exist in NSDocument on OS X:

 //doc is an instance of subclassed UIDocument [doc openWithCompletionHandler:nil]; 

Apple documentation provides this code for OS X:

 - (void)checkIfCloudAvaliable { NSURL *ubiquityContainerURL = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@"Documents"]; if (ubiquityContainerURL == nil) { NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: NSLocalizedString(@"iCloud does not appear to be configured.", @""), NSLocalizedFailureReasonErrorKey, nil]; NSError *error = [NSError errorWithDomain:@"Application" code:404 userInfo:dict]; [self presentError:error modalForWindow:[self windowForSheet] delegate:nil didPresentSelector:NULL contextInfo:NULL]; return; } dest = [ubiquityContainerURL URLByAppendingPathComponent: [[self fileURL] lastPathComponent]]; } - (void)moveToOrFromCloud { dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(globalQueue, ^(void) { NSFileManager *fileManager = [[NSFileManager alloc] init]; NSError *error = nil; // Move the file. BOOL success = [fileManager setUbiquitous:YES itemAtURL:[self fileURL] destinationURL:dest error:&error]; dispatch_async(dispatch_get_main_queue(), ^(void) { if (! success) { [self presentError:error modalForWindow:[self windowForSheet] delegate:nil didPresentSelector:NULL contextInfo:NULL]; } }); }); [self setFileURL:dest]; [self setFileModificationDate:nil]; } 

How can I sync between iOS and OS X (because NSDocument does not exist on iOS, and UIDocument does not exist on OS X)? Does anyone know where I can find a sample for Mac OSX ( NSDocument syncing)?

+4
source share
3 answers

I managed to get it to work! Here is my code from a subclass of on OS X:

Header file:

 #import <Cocoa/Cocoa.h> #import <Foundation/Foundation.h> @interface subclassedNSDocument : NSDocument @property (strong) NSData *myData; @end 

Implementation File:

 - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { BOOL readSuccess = NO; if (data) { readSuccess = YES; [self setMyData:data]; } [[NSNotificationCenter defaultCenter] postNotificationName:@"dataModified" object:self]; return readSuccess; } - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError { if (!myData && outError) { *outError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:nil]; } return myData; } 

and in the file AppDelegate.m:

 #define kFILENAME @"mydocument.dox" - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; if (ubiq) { NSLog(@"iCloud access at %@", ubiq); // TODO: Load document... [self loadDocument]; } else { NSLog(@"No iCloud access"); } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataReloaded:) name:@"dataModified" object:nil]; } - (void)update_iCloud { NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:kFILENAME]; self.doc.myData = [NSKeyedArchiver archivedDataWithRootObject:[@"Your Data Array or any data", nil]]; [self.doc saveToURL:ubiquitousPackage ofType:@"dox" forSaveOperation:NSSaveOperation error:nil]; } - (void)loadData:(NSMetadataQuery *)query { if ([query resultCount] == 1) { NSMetadataItem *item = [query resultAtIndex:0]; NSURL *url = [item valueForAttribute:NSMetadataItemURLKey]; NSLog(@"url = %@",url); subclassedNSDocument *doc = [[subclassedNSDocument alloc] initWithContentsOfURL:url ofType:@"dox" error:nil]; [doc setFileURL:url]; self.doc = doc; } else { NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:kFILENAME]; dataUrls *doc = [[dataUrls alloc] init]; [self.doc setFileURL:ubiquitousPackage]; self.doc = doc; [self.doc saveToURL:ubiquitousPackage ofType:@"dox" forSaveOperation:NSSaveOperation error:nil]; } } - (void)queryDidFinishGathering:(NSNotification *)notification { NSMetadataQuery *query = [notification object]; [query disableUpdates]; [query stopQuery]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query]; _query = nil; [self loadData:query]; } - (void)loadDocument { NSMetadataQuery *query = [[NSMetadataQuery alloc] init]; _query = query; [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]]; NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, kFILENAME]; [query setPredicate:pred]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query]; [query startQuery]; } - (void)dataReloaded:(NSNotification *)notification { self.doc = notification.object; NSArray *arrFromCloud = [NSKeyedUnarchiver unarchiveObjectWithData:self.doc.myData]; //Update you UI with new data } 

The only thing that did not work out for me is that if I change the document data on the iPad, the Mac application will not call the readFromData method to update from iCloud, does anyone know what I am missing?

On iOS, the equivalent loadFromContents method is called automatically every time a UIDocument in iCloud. In OS X, readFromData is called once at boot time, but never called again.

I hope my code can help, for me it works in one direction from Mac to iPad.

+5
source

I think NSMetadataQueryDidUpdateNotification is what you are looking for to detect document updates.

This can be used in the same way as NSMetadataQueryDidFinishGatheringNotification .

+2
source

If you are dealing with files in addition to the master data. Here is the best tutorial

http://samvermette.com/312

0
source

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


All Articles