6

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

4

2 回答 2

4

是的。iCloud 在 Mac 上可用。
但是 Apple 关于这个主题的文档仍然不是很完整。我能找到的唯一官方资源是 WWDC 2011 session 107 视频和“Mac OS X 中的新功能”中的一些注释

当 Lion 和 iCloud 仍处于 NDA 之下时,我在 Apple 的开发论坛上发布了我的发现。
这是这篇文章的编辑版本:

我正在使用 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 支持
  • 在 Developer Certificate Utility 中创建一个普遍存在的容器 ID
  • Ubiquity 容器 ID 以您的团队 ID/个人 ID 开头(请参阅会员中心的帐户选项卡)
  • 在 Xcode 中启用权利
  • 将您的 ubiquity 容器 ID 添加到权利文件(如此处“为 iCloud 存储请求权利”中所述。)
  • 我的 plist Bundle ID 必须与无处不在的容器 ID 匹配(团队 ID 除外)
  • 我无法添加后缀(例如“app.example.osx”、“app.example.ipad”、...如上述文档中所建议的那样)
  • 创建配置文件
  • 确保配置文件已安装在您的开发机器上并显示在 Xcode 和系统偏好设置中
  • 在您的应用构建设置中启用代码签名
于 2011-12-04T15:18:28.027 回答
1

Apple 有一个文档在各个方面都非常详细http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/iCloud/iCloud.html

此处发布的代码的一个重要问题是,即使清单中提到了 URLForUbiquityContainerIdentifier 的标识符,它也没有团队,将其完全保留为 nil 以从权利中自动填充似乎是最好的方法。

就我个人而言,要让 iCloud 在我的应用程序中运行,我必须做的唯一更改是:

  1. 检查开发者网站上的“使用 iCloud”按钮以获取我的应用程序 ID
  2. 下载该应用程序 ID 的重新生成条款
  3. 检查 xcode 摘要中的“启用权利”

就是这样,这是一个希望更清晰的示例代码(应该适用于 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]);               
    }      
}
于 2012-01-30T23:03:57.883 回答