Как синхронизировать NSDocument с iPad/iPhone на Mac OSX с помощью iCloud
Как синхронизировать nsdocument с ipad / iphone на Mac OS X с помощью icloud
Мне удалось заставить это работать! с Mac OS X на iPhone / iPad, но не с iPad / iPhone на Mac OS X
Вот мой код из файла подкласса nsdocument на osx:
Заголовочный файл:
#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
@interface subclassedNSDocument : NSDocument
@property (strong) NSData *myData;
@end
Файл реализации:
- (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;
}
и в файле 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
}
Вопрос в том, что у меня не работает только одна вещь : если я изменю данные документа на iPad, приложение Mac не вызовет readFromData
способ обновления из iCloud, кто-нибудь знает, что мне не хватает?
На iOS эквивалентный метод, loadFromContents
, вызывается автоматически при каждом изменении UIDocument
в iCloud. На OS X readFromData
вызывается один раз при загрузке, но никогда не вызывается снова.
Надеюсь, мой код может помочь, для меня он работает в одну сторону от Mac до iPad.
1 ответ
Исправил это сам.
По-видимому, это просто плохо реализованный и слишком сложный пример кода.
На applicationDidFinishLaunching:
нам просто нужно
_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];
И добавьте следующий метод:
- (void)queryUpdated:(NSNotification *)notification {
NSLog(@"queryUpdated called...");
NSMetadataQuery *query = [notification object];
[query disableUpdates];
if ([query resultCount] == 1) {
// update views, etc. here
}
[query enableUpdates];
}
Затем удалите все невостребованные методы из исходного образца.