我已经看过iOS的iCloud Document示例代码,我用它来同步i uidocument和iCloud,现在我试图在Mac OSX应用程序上同步iCloud和nsdocument没有UIDocument
。
我尝试将UIDocument
更改为NSDocument
,但与icloud同步的所有方法都不同。我没有找到任何示例代码或教程,除了来自apple的文档,这些文档非常令人困惑且写得不好。
例如,下面的方法,来自iOS上的UIDocument
在OS X上的NSDocument
中不存在:
//doc is an instance of subclassed UIDocument
[doc openWithCompletionHandler:nil];
Apple文档为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];
}
如何在iOS和OS X之间进行同步(因为iOS上不存在NSDocument
,OS X上不存在UIDocument
)?有谁知道我在哪里可以找到Mac OSX的样本(NSDocument
同步)?
答案 0 :(得分:5)
我设法让它发挥作用!这是我在OS X上的子类nsdocument文件中的代码:
标题文件:
#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上,iCloud中loadFromContents
的每次更改都会自动调用等效方法UIDocument
。在OS X上,readFromData
在加载时被调用一次但从未再次被调用。
希望我的代码可以提供帮助,对我来说,它是从Mac到iPad的单向工作。
答案 1 :(得分:2)
我认为NSMetadataQueryDidUpdateNotification
正是您要检测文档更新的目的。
这可以像NSMetadataQueryDidFinishGatheringNotification
一样使用。
答案 2 :(得分:0)
如果您正在处理除核心数据之外的文件。这是一个更好的教程