35

ローカルドキュメントフォルダ内のファイルにデータを保存するiPhoneアプリをすでに持っています。今私はiCloudテクノロジーについて学びました、そして私の最初の質問は:時々私が新しいバージョンをチェックするときにディレクトリとしてiCloudを使う方法はありますか?

つまり、UIDocument、ファイルコーディネーター、ファイルプレゼンターの使用を避けることはできますか?iCloudを特別なフォルダのように扱い、NSFileManagerのみを使用してファイルをプッシュおよび取得できるかどうかを知りたいだけです。

最後の注意:私はCore Dataやデータベースを使用せず、データファイルしか持っていません。

編集:

私はすでに公式のAppleiCloudドキュメントを読んだので、それらにリンクしないでください。いくつかのコード例だけが必要です。

4

5 に答える 5

26

私にとって「機能する」のは単純です。

NSFileManager *fm = [NSFileManager defaultManager];

NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

if (ubiq == nil) {
    return NO;
}

NSError *theError = nil;

[fm setUbiquitous:true itemAtURL:backupUrl destinationURL:[[ubiq URLByAppendingPathComponent:@"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError];

Appleは非UIスレッドを呼び出すように言っています。ファイルを「移動」させる。NSMetaDataQuery次のようにクエリを実行できます。

self.query = [[NSMetadataQuery alloc] init];
[self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K like '*.db'", NSMetadataItemFSNameKey];
[self.query setPredicate:pred];
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(queryDidFinishGathering:) 
                                             name:NSMetadataQueryDidFinishGatheringNotification 
                                           object:self.query];

[self.query startQuery];

- (void)queryDidFinishGathering:(NSNotification *)notification {
    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    [self loadData:query];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];

    self.query = nil; 
}

クエリ結果による列挙のサンプル:

- (void)loadData:(NSMetadataQuery *)query {
    [self.backups removeAllObjects];

    for (NSMetadataItem *item in [query results]) {
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
        [self.backups addObject:url.lastPathComponent];
    }

    [_table reloadData];

    [self.loadingBackupIndicator stopAnimating];
    self.loadingIndicatorLabel.text = [NSString stringWithFormat: @"%d backups found", [self.backups count]];
}

そして、具体的なファイルの「ダウンロード」を開始するには:

NSFileManager *fm = [NSFileManager defaultManager];

NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

if (ubiq == nil) {
    return NO;
}

NSError *theError = nil;

bool started = [fm startDownloadingUbiquitousItemAtURL:[[ubiq URLByAppendingPathComponent:@"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError];

NSLog(@"started download for %@ %d", backupName, started);

if (theError != nil) {
    NSLog(@"iCloud error: %@", [theError localizedDescription]);
}

「ダウンロード中」のファイルをチェックします。

- (BOOL)downloadFileIfNotAvailable {
    NSNumber *isIniCloud = nil;

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

    NSURL *file = [[ubiq URLByAppendingPathComponent:@"Documents" isDirectory:true] URLByAppendingPathComponent:self.backupName];

    if ([file getResourceValue:&isIniCloud forKey:NSURLIsUbiquitousItemKey error:nil]) {
        // If the item is in iCloud, see if it is downloaded.
        if ([isIniCloud boolValue]) {
            NSNumber*  isDownloaded = nil;
            if ([file getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:nil]) {
                if ([isDownloaded boolValue]) {
                    [self.loadingBackupIndicator stopAnimating];
                    self.loadingIndicatorLabel.text = @"Downloaded";

                    ....

                    [[NSFileManager defaultManager] copyItemAtPath:[file path] toPath:restorePath error:&theError ];

                    ....

                    return YES;
                }

                self.loadingCheckTimer = [NSTimer timerWithTimeInterval:3.0f target:self selector:@selector(downloadFileIfNotAvailable) userInfo:nil repeats:NO];
                [[NSRunLoop currentRunLoop] addTimer:self.loadingCheckTimer forMode:NSDefaultRunLoopMode];

                return NO;
            }
        }
    }

    return YES;
}

コードがそれほど長くなるとは思っていませんでした。ここで非常に生のスニペットを提供して申し訳ありません。上記は、概念を共有するだけで、コードの本番品質になる可能性があると言うつもりはありません。

私はまだそれを私のアプリ内でAppleに提出していないので、それがアプリストアに「承認」されるとは言えません(彼らが見つけたり気にかけたりした場合...)

于 2011-12-04T22:28:09.850 に答える
17

私はあなたがどのように感じているか知っています、iCloudは少し気が遠くなるようなものです。しかし、UIDocumentやファイルコーディネーターなどを回避して、iCloudを単純なフォルダとして使用する方法はないと思います。

わかりやすいサンプルコードをお探しの場合は、次の投稿をご覧ください。

iCloudの基本とコードサンプル

私はiCloudの最低限をカバーし、ディレクトリのようにそれをほとんど使用する完全なサンプルコードを含めました。おそらくこれにより、UIDocumentやファイルコーディネーターなどを使用するのが難しくなります。

しかし、あなたのように、古き良きドキュメンタリーフォルダーのアイデアとのより簡単で互換性のある方法があればいいのにと思います。ただし、これはiCloudであり、iCloudはさらにいくつかのことを行うため(さまざまなデバイスですべての同期を維持する、クラウドに絶えず更新するなど)、UIDocumentなどを回避する方法はありません。

于 2011-10-22T09:45:34.440 に答える
14

NSFileManagerを使用して、個々のファイルをiCloudにアップロードできます。これを行う方法についての完全なウォークスルーをブログに投稿しましたが、関連するNSFileManagerコードは次のとおりです。

NSURL *destinationURL = [self.ubiquitousURL URLByAppendingPathComponent:@"Documents/image.jpg"]
[[NSFileManager defaultManager] setUbiquitous:YES 
                                    itemAtURL:sourceURL
                               destinationURL:destinationURL
                                        error:&error]
于 2012-02-07T22:46:33.637 に答える
8

UIDocumentを使用する方法は実際にはありません。私はiCloudの最初の使用の1つでそれをやろうとしましたが、UIDocumentなしでは災害であることがわかりました。UIDocumentを使用することは、最初は多くの余分な作業のように思えますが、そうではありません。

UIDocumentを1時間以内に簡単にサブクラス化し、任意のタイプのファイルで機能させることができます(contentプロパティをNSDataとして設定するだけです)。また、標準のファイルシステムに比べて多くの利点があります。

  • 変更の追跡
  • ファイルの競合解決
  • ドキュメントの状態のサポート
  • 強化された保存/開く/閉じる機能

正直なところ、Appleのドキュメントを1、2時間読んでからそれを使用することは、時間と頭脳の力に見合うだけの価値があります。iCloudドキュメントストレージに関する優れたスターター記事は、AppleのDeveloperDocumentationにあります。


あらゆるタイプのファイル(具体的にはNSData)で機能するUIDocumentサブクラスを作成しました。GitHubでUIDocumentサブクラスのコードを表示、ダウンロード、変更できます。

ドキュメントを作成します。

// Initialize a document with a valid file path
iCloudDocument *document = [[iCloudDocument alloc] initWithFileURL:fileURL];

// Set the content of the document
document.contents = content;

// Increment the change count
[document updateChangeCount:UIDocumentChangeDone];

既存のドキュメントを保存します。

// Save and close the document
[document closeWithCompletionHandler:nil];

新しいドキュメントを保存します。

[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:nil];

NSMetadataQueryを使用して、iCloud内に保存されているすべてのファイルを同期することもできます。Appleは、NSMetadataクエリを使用してアプリファイルを同期する非常に優れた例を提供しています。また、これらの操作を実行する前に、必ずiCloudを確認してください(ヒント:ubiquityIdentityTokenNSFileManagerのメソッドを使用してください)。


iCloudDocumentSyncなどのオープンソースライブラリの使用を検討することもできます。iCloud Document Syncプロジェクトを使用すると、アプリファイルの保存と同期が非常に簡単になります。

1行のコードメソッドを使用してiCloudをiOSドキュメントプロジェクトに統合します。ドキュメントをiCloudからすばやく簡単に同期、アップロード、管理、削除します。開発者にとってもiCloudを「正しく機能させる」のに役立ちます。

ほとんどすべてのiCloudDocumentSyncメソッドでは、ファイルデータをパラメータとして渡すだけで、残り(保存、同期など)が処理されます。

免責事項:私はオープンソースプロジェクトであるiCloudDocumentSyncに貢献している開発者です。しかし、私はこのプロジェクトがあなたにとって有益であり、この質問に関連していると信じています。これは宣伝や宣伝ではありません。

于 2013-11-16T16:28:45.427 に答える
-1

このコードを使用します:

+ (NSString *)Pathsave {
    NSString *os5 = @"5.0";

    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

    if ([currSysVer compare:os5 options:NSNumericSearch] == NSOrderedAscending) {
       // Lower than 4
        return path;
    } else if ([currSysVer compare:os5 options:NSNumericSearch] == NSOrderedDescending) {
        // 5.0.1 and above        
        return path;
    } else {
        // iOS 5
        path = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
        return path;
    }

    return nil;
}
于 2013-05-22T07:01:37.670 に答える