Сохранить документы iOS 8 на iCloud Drive
Я хочу, чтобы мое приложение сохраняло документы, которые оно создает, в iCloud Drive, но мне трудно следовать тому, что написала Apple. Вот то, что я имею до сих пор, но я не уверен, куда идти отсюда.
UPDATE2
В моем коде есть следующее, чтобы вручную сохранить документ на iCloud Drive:
- (void)initializeiCloudAccessWithCompletion:(void (^)(BOOL available)) completion {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
self.ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (self.ubiquityURL != nil) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"iCloud available at: %@", self.ubiquityURL);
completion(TRUE);
});
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"iCloud not available");
completion(FALSE);
});
}
});
}
if (buttonIndex == 4) {
[self initializeiCloudAccessWithCompletion:^(BOOL available) {
_iCloudAvailable = available;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:selectedCountry];
NSURL* url = [NSURL fileURLWithPath: pdfPath];
[self.manager setUbiquitous:YES itemAtURL:url destinationURL:self.ubiquityURL error:nil];
}];
}
У меня есть права, установленные для идентификатора приложения и в самом XCode. Я нажимаю кнопку, чтобы сохранить на iCloud Drive, и не появляется никаких ошибок, приложение не падает, но на моем Mac в iCloud Drive ничего не отображается. Приложение работает на моем iPhone 6 Plus через Test Flight при использовании iOS 8.1.1.
Если я запускаю его на симуляторе (я знаю, что он не будет работать из-за того, что iCloud Drive не работает с симулятором), я получаю ошибку сбоя: 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[3]'
2 ответа
Ну, ты сам заинтересовал меня этим вопросом, и в результате я потратил много времени на этот вопрос, но теперь, когда он у меня работает, я надеюсь, что он тебе тоже поможет!
Чтобы увидеть, что на самом деле происходит в фоновом режиме, вы можете взглянуть на ~/Library/Mobile Documents/
, поскольку это папка, где файлы в конечном итоге будут отображаться. Еще одна очень крутая утилита brctl
, чтобы отслеживать, что происходит на вашем Mac после сохранения файла в iCloud. Бежать brctl log --wait --shorten
из окна терминала, чтобы начать журнал.
Первое, что нужно сделать после включения возможности iCloud (с выбранными документами iCloud), это предоставить информацию для поддержки iCloud Drive ( Включение поддержки iCloud Drive). Мне также пришлось столкнуться с версией пакета, прежде чем снова запустить приложение; Мне понадобилось время, чтобы понять это. Добавьте следующее к вашему info.plist
:
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.YOUR_BUNDLE_IDENTIFIER</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
<key>NSUbiquitousContainerName</key>
<string>iCloudDriveDemo</string>
</dict>
</dict>
Далее код:
- (IBAction)btnStoreTapped:(id)sender {
// Let's get the root directory for storing the file on iCloud Drive
[self rootDirectoryForICloud:^(NSURL *ubiquityURL) {
NSLog(@"1. ubiquityURL = %@", ubiquityURL);
if (ubiquityURL) {
// We also need the 'local' URL to the file we want to store
NSURL *localURL = [self localPathForResource:@"demo" ofType:@"pdf"];
NSLog(@"2. localURL = %@", localURL);
// Now, append the local filename to the ubiquityURL
ubiquityURL = [ubiquityURL URLByAppendingPathComponent:localURL.lastPathComponent];
NSLog(@"3. ubiquityURL = %@", ubiquityURL);
// And finish up the 'store' action
NSError *error;
if (![[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:localURL destinationURL:ubiquityURL error:&error]) {
NSLog(@"Error occurred: %@", error);
}
}
else {
NSLog(@"Could not retrieve a ubiquityURL");
}
}];
}
- (void)rootDirectoryForICloud:(void (^)(NSURL *))completionHandler {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *rootDirectory = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]URLByAppendingPathComponent:@"Documents"];
if (rootDirectory) {
if (![[NSFileManager defaultManager] fileExistsAtPath:rootDirectory.path isDirectory:nil]) {
NSLog(@"Create directory");
[[NSFileManager defaultManager] createDirectoryAtURL:rootDirectory withIntermediateDirectories:YES attributes:nil error:nil];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(rootDirectory);
});
});
}
- (NSURL *)localPathForResource:(NSString *)resource ofType:(NSString *)type {
NSString *documentsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *resourcePath = [[documentsDirectory stringByAppendingPathComponent:resource] stringByAppendingPathExtension:type];
return [NSURL fileURLWithPath:resourcePath];
}
У меня есть файл с именем demo.pdf
хранится в папке "Документы", которую я буду "загружать".
Я выделю некоторые части:
URLForUbiquityContainerIdentifier:
предоставляет корневой каталог для хранения файлов. Если вы хотите, чтобы они отображались в de iCloud Drive на вашем Mac, вам необходимо сохранить их в папке "Документы", поэтому здесь мы добавляем эту папку в корневой каталог:
NSURL *rootDirectory = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]URLByAppendingPathComponent:@"Documents"];
Вам также нужно добавить имя файла в URL, здесь я копирую имя файла из localURL (который является demo.pdf):
// Now, append the local filename to the ubiquityURL
ubiquityURL = [ubiquityURL URLByAppendingPathComponent:localURL.lastPathComponent];
И это в основном все...
В качестве бонуса, проверьте, как вы можете предоставить NSError
указатель для получения информации о потенциальной ошибке:
// And finish up the 'store' action
NSError *error;
if (![[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:localURL destinationURL:ubiquityURL error:&error]) {
NSLog(@"Error occurred: %@", error);
}
Если вы собираетесь работать с UIDocument и iCloud, это руководство от Apple довольно неплохо: https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html
ИЗДАНО: Не знаю лучшего руководства, так что это может помочь:
Вам нужно будет получить ubiquityURL, используя URLForUbuiquityContainerIdentifier
функция на NSFileManager
(что должно быть сделано асинхронно). Как только это будет сделано, вы можете использовать код, подобный следующему, для создания вашего документа.
NSString* fileName = @"sampledoc";
NSURL* fileURL = [[self.ubiquityURL URLByAppendingPathComponent:@"Documents" isDirectory:YES] URLByAppendingPathComponent:fileName isDirectory:NO];
UIManagedDocument* document = [[UIManagedDocument alloc] initWithFileURL:fileURL];
document.persistentStoreOptions = @{
NSMigratePersistentStoresAutomaticallyOption : @(YES),
NSInferMappingModelAutomaticallyOption: @(YES),
NSPersistentStoreUbiquitousContentNameKey: fileName,
NSPersistentStoreUbiquitousContentURLKey: [self.ubiquityURL URLByAppendingPathComponent:@"TransactionLogs" isDirectory:YES]
};
[document saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
}];
Вы также хотите посмотреть на использование NSMetadataQuery
обнаруживать документы, загруженные с других устройств, и, возможно, ставить их в очередь для загрузки и наблюдать за NSPersistentStoreDidImportUbiquitousContentChangesNotification
чтобы узнать об изменениях, сделанных через iCloud, между прочим.
** Редактировать 2 **
Похоже, вы пытаетесь сохранить файл PDF, что не совсем то, что Apple считает "документом" с точки зрения синхронизации iCloud. Нет необходимости использовать UIManagedDocument. Удалите последние 3 строки вашего обработчика завершения и вместо этого просто используйте NSFileManager's setUbiquitous:itemAtURL:destinationURL:error:
функция. Первый URL должен быть локальным путем к PDF. Второй URL должен быть путем в контейнере ubiquiuty, чтобы сохранить как.
Вам также может понадобиться заглянуть в NSFileCoordinator, возможно. Я думаю, что это руководство от Apple может быть наиболее актуальным: https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html