web-dev-qa-db-ja.com

iOS8ドキュメントをiCloudドライブに保存する

作成したドキュメントをアプリにiCloudDriveに保存させたいのですが、Appleが書いたものをフォローするのに苦労しています。これまでのところ、これが私ですが、 mここからどこへ行くのかわからない。

PDATE2

ドキュメントをiCloudドライブに手動で保存するためのコードには次のものがあります。

- (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];


    }];

       }

アプリIDとXcode自体に資格を設定しました。ボタンをクリックしてiCloudドライブに保存しましたが、エラーは表示されず、アプリはクラッシュしませんが、MacのiCloudドライブに何も表示されません。このアプリは、iOS 8.1.1を使用しているときに、テストフライトを介してiPhone 6Plusで実行されています。

シミュレーターで実行すると(iCloudドライブがシミュレーターで動作しないために動作しないことがわかっています)、クラッシュエラーが発生します:'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[3]'

10
user717452

さて、あなたは私自身がこの問題に興味を持ってくれたので、結果として私はこの質問に多くの時間を費やしました、しかし今私はそれが機能するようになったのでそれがあなたにも役立つことを願っています!

File on my Mac

バックグラウンドで実際に何が起こっているかを確認するには、~/Library/Mobile Documents/を確認します。これは、ファイルが最終的に表示されるフォルダーです。もう1つの非常に優れたユーティリティはbrctlで、iCloudにファイルを保存した後にMacで何が起こるかを監視します。ターミナルウィンドウからbrctl log --wait --shortenを実行して、ログを開始します。

(iCloudドキュメントを選択して)iCloud機能を有効にした後、最初に行うことは、iCloudドライブサポートの情報を提供することです( iCloudドライブサポートの有効化 )。 アプリを再度実行する前に、バンドルバージョンをバンプする必要もありました。これを理解するのに少し時間がかかりました。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];
}

Documentsフォルダにdemo.pdfというファイルが保存されています。これを「アップロード」します。

いくつかの部分を強調します:

URLForUbiquityContainerIdentifier:は、ファイルを保存するためのルートディレクトリを提供します。ファイルをMacのde iCloudドライブに表示する場合は、ファイルを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);
}
35
fguchelaar

UIDocumentとiCloudを使用する場合は、Appleからのこのガイドはかなり良いです: https://developer.Apple.com/library/ios/documentation/DataManagement/ Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html

[〜#〜]編集済み[〜#〜]:より良い手のガイドがわからないので、これは役立つかもしれません:

URLForUbuiquityContainerIdentifierNSFileManager関数を使用して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へのローカルパスである必要があります。2番目のURLは、名前を付けて保存するユビキタスコンテナ内のパスである必要があります。

おそらくNSFileCoordinatorを調べる必要があるかもしれません。 Appleのこのガイドが最も関連性があると思います: https://developer.Apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud .html

1
zeroimpl