【问题标题】:Save iOS 8 Documents to iCloud Drive将 iOS 8 文档保存到 iCloud 云盘
【发布时间】:2015-01-19 00:18:57
【问题描述】:

我想让我的应用程序将它创建的文档保存到 iCloud Drive,但我很难按照 Apple 编写的内容进行操作。这是我到目前为止所拥有的,但我不确定从这里去哪里。

更新2

我的代码中有以下内容可以手动将文档保存到 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];


    }];

       }

我已为 App ID 和 Xcode 本身设置了权利。我单击按钮保存到 iCloud Drive,并且没有弹出错误,应用程序没有崩溃,但 iCloud Drive 中的 Mac 上没有显示任何内容。该应用程序在使用 iOS 8.1.1 时通过 Test Flight 在我的 iPhone 6 Plus 上运行。

如果我在模拟器上运行它(我知道它不会工作,因为 iCloud Drive 不能与模拟器一起工作),我会收到崩溃错误:'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[3]'

【问题讨论】:

  • setUbiquitous:itemAtURL:destinationURL:error: 无论操作成功与否都返回一个 BOOL。返回值是多少?还为error 参数提供指向NSError 对象的指针。如果方法返回 NO,这可能会给你更多的指导。
  • @fguchelaar 抱歉,我从来没有对 NSFileManager 搞砸过,所以其中一些内容超出了我的想象。

标签: ios xcode ios8 icloud uidocument


【解决方案1】:

嗯,你让我自己对这个问题感兴趣,因此我在这个问题上花了很多时间,但现在我已经开始工作了,我希望它对你也有帮助!

要查看后台实际发生的情况,您可以查看~/Library/Mobile Documents/,因为这是文件最终会显示的文件夹。另一个非常酷的实用程序是brctl,用于监控将文件存储在 iCloud 中后 Mac 上发生的情况。从终端窗口运行 brctl log --wait --shorten 以启动日志。

启用 iCloud 功能(选择 iCloud 文档)后,首先要做的是提供 iCloud Drive Support 信息 (Enabling iCloud Drive Support)。 在再次运行应用程序之前,我还必须升级我的捆绑包版本;我花了一些时间来解决这个问题。将以下内容添加到您的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 的文件存储在 Documents 文件夹中,我将“上传”该文件。

我会强调一些部分:

URLForUbiquityContainerIdentifier: 提供了存储文件的根目录,如果你想让它们显示在你 Mac 上的 iCloud Drive 中,那么你需要将它们存储在 Documents 文件夹中,所以这里我们将该文件夹添加到根目录:

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

【讨论】:

  • 看起来我正在发送我的文件(我收到一个错误:当我尝试多次写入同一个文件时文件已经存在),我在我的brutal log 中看到了一些东西Mac,但我在 iCloud.com 或我的 Mac 上看不到该文件夹​​。有什么想法为什么会这样?
  • 编辑:必须增加 CFBundleVersion。令人抓狂! stackoverflow.com/a/25328864/1148702
  • 我知道,疯了..我会再强调一下我的回答,你似乎忽略了它:)
  • 如何从 iCloud Drive 中检索文件?
  • 也许这很明显,但我第一次错过了...如果您使用的是自定义 iCloud 容器,则必须使用它来代替 iCloud.YOUR_BUNDLE_IDENTIFIER。
【解决方案2】:

如果您打算使用 UIDocument 和 iCloud,Apple 的这份指南非常好: https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html

已编辑: 不知道任何更好的手部指南,所以这可能会有所帮助:

您需要使用NSFileManager 上的URLForUbuiquityContainerIdentifier 函数获取ubiquityURL(应该异步完成)。 完成后,您可以使用如下代码创建文档。

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 的 setUbiquitous:itemAtURL:destinationURL:error: 函数。第一个 URL 应该是 PDF 的本地路径。第二个 URL 应该是通用容器中要另存为的路径。

您可能还需要查看 NSFileCoordinator。 我认为 Apple 的这份指南可能是最相关的: https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html

【讨论】:

  • 这有点帮助,我只是没有关注 Apple 如何写出他们所有的东西。我只是在寻找这样的内容,当您制作文档时,您会这样做,并将其存储到 iCloud,以便它出现在 iCloud Drive 中。
  • 请检查我原始问题的更新,看看我是否搞砸了。
  • 我现在将 Metadata.plist 文件保存到 iCloud Drive,但不是 PDF 本身。怎么了?
  • 你能帮帮我吗?
  • 那么像我如何编辑原始问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2015-11-24
  • 1970-01-01
  • 2015-12-05
相关资源
最近更新 更多