Реализация Apple iCloud в приложениях Mac - PullRequest
6 голосов
/ 04 декабря 2011

Мне известно, что в iOS есть API для интеграции iCloud для приложений. Могу ли я интегрировать iCloud в приложения для Mac? Будет ли отличаться реализация для приложений Mac для интеграции iCloud? Если да, есть ли учебники и т. Д. Или справочные сайты?

Ответы [ 2 ]

4 голосов
/ 04 декабря 2011

Да.iCloud доступен на Mac.
Но документация Apple по этой теме еще не очень полная.Единственные официальные ресурсы, которые я смог найти, где видео сеанса 107 WWDC и некоторые заметки в «Что нового в Mac OS X»

Когда Lion и iCloud еще былипод NDA я опубликовал свои выводы в devforums Apple.
Это отредактированная версия этого поста :

Я использую модифицированную версию кода 107-й сессии WWDC 2011.(переписано из видео) Мне пришлось удалить ручное создание экземпляра 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 в Утилите сертификата разработчика
  • Создайте идентификатор контейнера ubiquity в Утилите сертификата разработчика
  • Идентификатор контейнера Ubiquity начинается с вашего идентификатора команды / физического лицаИдентификатор (см. Вкладку учетной записи в центре участников)
  • Включить права доступа в Xcode
  • Добавьте свой идентификатор контейнера ubiquity в файл разрешений (как описано здесь «Запрос прав для хранилища iCloud».)
  • Мой идентификатор пакета plist должен совпадать с идентификатором контейнера ubiquity (кроме for идентификатор команды)
  • Мне не удалось добавить суффиксы (например, "app.example.osx", "app.example.ipad", ..., как предложено в документе выше)
  • Создание профиля обеспечения
  • Убедитесь, что профиль установлен на вашем компьютере разработчика и отображается в настройках Xcode и системы
  • Включение подписи кода в настройках сборки приложений
1 голос
/ 31 января 2012

Существует документ Apple, который подробно описан во всех аспектах http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/iCloud/iCloud.html

Одна существенная проблема с кодом, размещенным здесь, состоит в том, что у него нет команды в идентификаторе, заданном для URLForUbiquityContainerIdentifier, даже если онупомянуто в контрольном списке, оставляя ноль в целом для автоматического заполнения из прав, кажется лучшим подходом.

Лично единственные изменения, которые я должен был сделать, чтобы запустить iCloud в моем приложении, были:

  1. отметьте кнопку «использовать iCloud» на веб-сайте разработчика для идентификатора моего приложения
  2. загрузите восстановленное положение для этого идентификатора приложения
  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]);               
    }      
}
...