6

iOS にはアプリ用に iCloud を統合するための API があることは承知しています。Mac アプリにも iCloud を統合できますか? iCloud を統合するための Mac アプリの実装は異なりますか? はいの場合、チュートリアルなどや参考サイトはありますか?

4

2 に答える 2

4

はい。iCloudはMacで利用できます。
しかし、このトピックに関するAppleのドキュメントはまだ完全ではありません。WWDC2011セッション107のビデオと「MacOSXの新機能」のメモを見つけることができた唯一の公式リソース

LionとiCloudがまだNDAの下にあったとき、私は自分の調査結果をAppleの開発フォーラムに投稿しました。
これはこの投稿の編集版です:

WWDC2011セッション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を作成します
  • ユビキタスコンテナIDは、チームID /個人IDで始まります(メンバーセンターの[アカウント]タブを参照)
  • Xcodeでエンタイトルメントを有効にする
  • ユビキタスコンテナIDをエンタイトルメントファイルに追加します(「iCloudストレージのエンタイトルメントのリクエスト」で説明されています)。
  • 私のplistバンドル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

ここに投稿されたコードの重要な問題の 1 つは、チェックリストに記載されていても、URLForUbiquityContainerIdentifier に指定された識別子にチームがないことです。権限から自動的に入力されるように、完全にゼロのままにしておくのが最善のアプローチのようです。

個人的には、アプリで iCloud を使用するために必要な唯一の変更は次のとおりです。

  1. アプリIDの開発者Webサイトの「iCloudを使用」ボタンを確認してください
  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 に答える