xcode 将 iOS 8 文档保存到 iCloud Drive
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27051437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Save iOS 8 Documents to iCloud Drive
提问by user717452
I want to have my app save the documents it creates to iCloud Drive, but I am having a hard time following along with what Apple has written. Here is what I have so far, but I'm not for sure where to go from here.
我想让我的应用程序将它创建的文档保存到 iCloud Drive,但我很难跟随 Apple 编写的内容。到目前为止,这是我所拥有的,但我不确定从哪里开始。
UPDATE2
更新2
I have the following in my code to manually save a document to iCloud Drive:
我的代码中有以下内容可以手动将文档保存到 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];
}];
}
I have the entitlements set up for the App ID and in Xcode itself. I click the button to save to iCloud Drive, and no errors pop up, the app doesn't crash, but nothing shows up on my Mac in iCloud Drive. The app is running on my iPhone 6 Plus via Test Flight while using iOS 8.1.1.
我为 App ID 和 Xcode 本身设置了权限。我单击按钮保存到 iCloud Drive,没有弹出错误,应用程序没有崩溃,但我的 Mac 上的 iCloud Drive 没有显示任何内容。该应用程序在我的 iPhone 6 Plus 上通过 Test Flight 运行,同时使用 iOS 8.1.1。
If I run it on Simulator (I know that it won't work due to iCloud Drive not working with simulator), I get the crash error: 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[3]'
如果我在模拟器上运行它(我知道由于 iCloud Drive 无法与模拟器一起工作而无法运行),我会收到崩溃错误: 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[3]'
回答by fguchelaar
Well, you've got me interested in this matter myself and as a result I've spent way to much time on this question, but now that I've got it working I hope it helps you as well!
好吧,你让我自己对这件事感兴趣,因此我在这个问题上花了很多时间,但现在我已经开始工作了,我希望它也能帮助你!
To see what actually happens in the background, you can have a look at ~/Library/Mobile Documents/
, as this is the folder where the files eventually will show up. Another very cool utility is brctl
, to monitor what happens on your mac after storing a file in the iCloud. Run brctl log --wait --shorten
from a Terminal window to start the log.
要查看后台实际发生的情况,您可以查看~/Library/Mobile Documents/
,因为这是文件最终将显示的文件夹。另一个非常酷的实用程序是brctl
,在将文件存储到 iCloud 后监控 Mac 上发生的情况。brctl log --wait --shorten
从终端窗口运行以启动日志。
First thing to do, after enabling the iCloud ability (with iCloud documents selected), is provide information for iCloud Drive Support (Enabling iCloud Drive Support). I also had to bump my bundle version before running the app again; took me some time to figure this out.Add the following to your info.plist
:
在启用 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>
Next up, the code:
接下来,代码:
- (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];
}
I have a file called demo.pdf
stored in the Documents folder, which I'll be 'uploading'.
我有一个名为demo.pdf
Documents 文件夹中的文件,我将对其进行“上传”。
I'll highlight some parts:
我将重点介绍一些部分:
URLForUbiquityContainerIdentifier:
provides the root directory for storing files, if you want to them to show up in de iCloud Drive on your Mac, then you need to store them in the Documents folder, so here we add that folder to the root:
URLForUbiquityContainerIdentifier:
提供用于存储文件的根目录,如果您希望它们显示在您的 Mac 上的 iCloud Drive 中,那么您需要将它们存储在 Documents 文件夹中,因此我们在这里将该文件夹添加到根目录:
NSURL *rootDirectory = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]URLByAppendingPathComponent:@"Documents"];
You also need to add the file name to the URL, here I copy the filename from the localURL (which is demo.pdf):
您还需要将文件名添加到 URL,这里我从 localURL(即 demo.pdf)复制文件名:
// Now, append the local filename to the ubiquityURL
ubiquityURL = [ubiquityURL URLByAppendingPathComponent:localURL.lastPathComponent];
And that's basically it...
基本上就是这样......
As a bonus, check out how you can provide an NSError
pointer to get potential error information:
作为奖励,请查看如何提供NSError
指针以获取潜在错误信息:
// And finish up the 'store' action
NSError *error;
if (![[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:localURL destinationURL:ubiquityURL error:&error]) {
NSLog(@"Error occurred: %@", error);
}
回答by zeroimpl
If you are intending to work with UIDocument and iCloud, this guide from Apple is pretty good: https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html
如果您打算使用 UIDocument 和 iCloud,Apple 的这份指南非常好:https: //developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html
EDITED: Don't know of any better guide of hand, so this may help:
编辑:不知道任何更好的手指南,所以这可能会有所帮助:
You will need to fetch the ubiquityURL using the URLForUbuiquityContainerIdentifier
function on NSFileManager
(which should be done asynchronously).
Once that is done, you can use code like the following to create your document.
您将需要使用URLForUbuiquityContainerIdentifier
on 函数获取 ubiquityURL 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) {
}];
You'll also want to look into using NSMetadataQuery
to detect documents uploaded from other devices and potentially queue them for download, and observing the NSPersistentStoreDidImportUbiquitousContentChangesNotification
to find about changes made via iCloud, among other things.
您还需要考虑使用它NSMetadataQuery
来检测从其他设备上传的文档,并可能将它们排入队列以供下载,并观察NSPersistentStoreDidImportUbiquitousContentChangesNotification
以查找通过 iCloud 所做的更改等。
** Edit 2 **
** 编辑 2 **
Looks like you are trying to save a PDF file, which is not quite what Apple considers a "document" in terms of iCloud syncing. No need to use UIManagedDocument. Remove the last 3 lines of your completion handler and instead just use NSFileManager's
setUbiquitous:itemAtURL:destinationURL:error:
function. The first URL should be a local path to the PDF. The second URL should be the path within the ubiquiuty container to save as.
看起来您正在尝试保存 PDF 文件,这在 iCloud 同步方面并不是 Apple 认为的“文档”。无需使用 UIManagedDocument。删除完成处理程序的最后 3 行,而只使用 NSFileManager 的
setUbiquitous:itemAtURL:destinationURL:error:
函数。第一个 URL 应该是 PDF 的本地路径。第二个 URL 应该是 ubiquiuty 容器中要另存为的路径。
You may also need to look into NSFileCoordinator perhaps. I think this guide from Apple may be the most relevant: https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html
您可能还需要查看 NSFileCoordinator 。我认为 Apple 的这份指南可能是最相关的:https: //developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html