Mac应用程序上的Apple iCloud实现

时间:2011-12-04 14:15:00

标签: macos icloud

我知道iOS有API为应用程序集成iCloud。 我也可以将iCloud集成到mac应用程序中吗? Mac应用程序集成iCloud的实现会有所不同吗? 如果是,是否有任何教程等或参考网站?

2 个答案:

答案 0 :(得分:4)

是。 iCloud可在Mac上使用 但Apple关于这个主题的文档仍然不是很完整。我可以在WWDC 2011 session 107 video"What's new in Mac OS X"中的一些笔记找到的唯一官方资源

Lion& iCloud仍然在NDA下我在Apple的devforums中发布了我的发现 这是this post的编辑版本:

我正在使用WWDC 2011 Session 107代码的修改版本。 (从视频转录) 我不得不删除NSFileCoordinator的手动实例化以使样本正常工作(发言者提到“未来可能不需要协调员”):

- (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];
     }
}

上述IBAction连接到NSMenuItem,用于检查文档是否已经在iCloud中,或者是否需要上传:

- (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;
}

使iCloud文档存储工作所需的非代码任务清单:

  • 检查开发人员证书实用程序
  • 中是否已激活iCloud支持
  • 在开发人员证书实用程序
  • 中创建普遍存在的容器ID
  • Ubiquity容器ID以您的团队ID /个人ID开头(请参阅会员中心的帐户标签)
  • 在Xcode中启用权利
  • 将您的ubiquity容器ID添加到权利文件中(如此处所述“请求iCloud存储的权利。”)
  • 我的plist Bundle ID必须与ubiquity容器ID匹配(团队ID除外)
  • 我无法添加后缀(例如“app.example.osx”,“app.example.ipad”,......如上文所示)
  • 创建配置文件
  • 确保配置文件已安装在您的开发计算机上并显示在Xcode&系统偏好设置
  • 在您的应用构建设置中启用代码签名

答案 1 :(得分:1)

Apple提供了一份文件,详细介绍了所有方面http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/iCloud/iCloud.html

这里发布的代码的一个重要问题是它没有给URLForUbiquityContainerIdentifier提供的标识符中的团队,即使在清单中提到它,也没有从权利中自动填充它似乎是最好的方法

就个人而言,我必须做的唯一改变才能让iCloud进入我的应用程序:

  1. 检查开发者网站上的“使用iCloud”按钮,查找我的应用ID
  2. 下载该应用ID的重新生成的配置
  3. 检查xcode摘要中的“启用权利”
  4. 就是这样,这是一个希望更清晰的示例代码(适用于iOS和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]);               
        }      
    }