问题
How to Sync an nsdocument from ipad/iphone to Mac osx with icloud
I managed to get it working! from Mac osx to iPhone/iPad but not from iPad/iPhone to Mac osx
Here's my code from the subclassed nsdocument file on osx:
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 AppDelegate.m file:
#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 question is:
The only thing that I haven't got working is that if I change the data of the document on the iPad, the Mac app doesn't call the readFromData
method for to update from iCloud, does anyone know what I am missing?
On iOS, the equivalent method, loadFromContents
, is called automatically on every change of the UIDocument
in iCloud. On OS X the readFromData
is called once on load but never called again.
Hope my code can help, for me it is working one way from Mac to iPad.
回答1:
Fixed it myself.
Apparently it's just a poorly implemented and over-complicated sample code.
On applicationDidFinishLaunching:
we just need
_query = [[NSMetadataQuery alloc] init];
[_query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, kFILENAME];
[_query setPredicate:pred];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidUpdateNotification object:_query];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidFinishGatheringNotification object:_query];
[_query startQuery];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataReloaded:) name:@"dataModified" object:nil];
And add the following method:
- (void)queryUpdated:(NSNotification *)notification {
NSLog(@"queryUpdated called...");
NSMetadataQuery *query = [notification object];
[query disableUpdates];
if ([query resultCount] == 1) {
// update views, etc. here
}
[query enableUpdates];
}
Then remove all the uncalled methods from the original sample.
来源:https://stackoverflow.com/questions/20984512/how-to-sync-an-nsdocument-from-ipad-iphone-to-mac-osx-with-icloud