0

アプリでiCloudUIDocumentを有効にし、ドキュメントをクラウドに保存し、ドキュメントをパッケージ化して、iCloudドキュメントの更新の通知を受け取ります:

- (void)startQuery {

    [self stopQuery];

    NSLog(@"Starting to watch iCloud dir...");

    _query = [self documentQuery];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(processiCloudFiles:)
                                                 name:NSMetadataQueryDidFinishGatheringNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(processiCloudFiles:)
                                                 name:NSMetadataQueryDidUpdateNotification
                                               object:nil];

    [_query startQuery];
}

- (void)stopQuery {

    if (_query) {

        NSLog(@"No longer watching iCloud dir...");

        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidUpdateNotification object:nil];
        [_query stopQuery];
        _query = nil;
    }

}

- (NSMetadataQuery *)documentQuery {

    NSMetadataQuery * query = [[NSMetadataQuery alloc] init];
    if (query) {

        [query setSearchScopes:[NSArray arrayWithObject:
                                 NSMetadataQueryUbiquitousDocumentsScope]];

        NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K == %@",
                             NSMetadataItemFSNameKey,
                             kFILENAME];
        [query setPredicate:pred];

    }
    return query;

}

- (void)processiCloudFiles:(NSNotification *)notification {

    [_query disableUpdates];

    if ([_query resultCount] == 1) {
        NSMetadataItem *item = [_query resultAtIndex:0];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

        if (!self.folder) {
            self.folder = [[MyDocument alloc] initWithFileURL:url];
        }
        [self.folder openWithCompletionHandler:^ (BOOL success) {
            if (success) {
                NSLog(@"loadData - doc opened from cloud %i", self.folder.count);
                [self.folder closeWithCompletionHandler:^(BOOL success) {
                    NSLog(@"doc closed");
                }
                 ];
            } else {
                NSLog(@"failed to open");
            } }];

    }
}

私が呼び出すすべてを開始する[self startQeury]には、問題はNSMetadataQueryDidUpdateNotification、ドキュメントに変更を加えた場合に通知を数回呼び出すことです。ログを確認する方法は次のとおりです。

2013-10-12 01:43:54.933  Starting to watch iCloud dir...
2013-10-12 01:43:56.119  loadData - doc opened from cloud 56
2013-10-12 01:43:56.120  doc closed
2013-10-12 01:44:01.552  item deleted

ここでわかるように、私は変更を加えます。以下では、スポーン 4 通知を確認できます。

2013-10-12 01:44:08.110  loadData - doc opened from cloud 55
2013-10-12 01:44:08.111  doc closed
2013-10-12 01:44:11.942  loadData - doc opened from cloud 55
2013-10-12 01:44:11.943  doc closed
2013-10-12 01:44:13.198  loadData - doc opened from cloud 55
2013-10-12 01:44:13.199  doc closed
2013-10-12 01:44:14.925  loadData - doc opened from cloud 55
2013-10-12 01:44:14.926  doc closed

なぜ複数回呼び出されるのですか?私のアプリでは、更新が完了したときに変更を処理する必要があるため、通知は 1 つだけ必要です...どうすればよいですか?

編集: 私は答えで@rmaddyが提案することを試しました、私はこれを試しました:

if ([[item valueForAttribute:NSMetadataUbiquitousItemIsDownloadedKey] boolValue]) {

        if (!self.folder) {
            self.tvfilesFolder = [[MyDocument alloc] initWithFileURL:url];
        }
        [self.folder openWithCompletionHandler:^ (BOOL success) {
            if (success) {
                NSLog(@"loadData - doc opened from cloud %i", self.folder.count);
                [self.folder closeWithCompletionHandler:^(BOOL success) {
                    NSLog(@"doc closed");
                }
                 ];
            } else {
                NSLog(@"failed to open");
            } }];
    }

しかし、やはり問題があります。これはログです:

2013-10-12 10:35:26.084 Starting to watch iCloud dir...
2013-10-12 10:35:30.306 loadData - doc opened from cloud 54
2013-10-12 10:35:30.307 doc closed

次に、ドキュメントを編集しました。これがログです。

2013-10-12 10:35:53.233 loadData - doc opened from cloud 54
2013-10-12 10:35:53.235 doc closed
2013-10-12 10:35:56.703 loadData - doc opened from cloud 54
2013-10-12 10:35:56.704 doc closed
2013-10-12 10:35:58.489 loadData - doc opened from cloud 54
2013-10-12 10:35:58.490 doc closed

どうすればいいですか?

編集2:

私はこれを試しました:

if ([[item valueForAttribute:NSMetadataUbiquitousItemIsDownloadedKey] boolValue] && [[item valueForAttribute:NSMetadataUbiquitousItemIsUploadedKey] boolValue]) {
....
}

うまくいっているようですが、どう思いますか? 変更があるたびに処理できますか、それともこの方法で通知を見逃す可能性がありますか?

4

1 に答える 1

0

通知はさまざまな理由で呼び出されます。ファイルが最初に iCloud にアップロードされたとき、およびファイルが iCloud からダウンロードされたとき。また、アップロードとダウンロードの割合に関する最新情報も入手できます。ファイルのさまざまなプロパティを見ると、これらすべてを確認できます。

各メタデータ項目をログに記録するために、ちょっとしたデバッグ方法を使用します。

- (void)echoMetadataItem:(NSMetadataItem *)item {
    NSString *path = [item valueForAttribute:NSMetadataItemPathKey];
    NSString *display = [item valueForAttribute:NSMetadataItemDisplayNameKey];
    NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
    NSString *name = [item valueForAttribute:NSMetadataItemFSNameKey];
    NSNumber *downloaded = [item valueForAttribute:NSMetadataUbiquitousItemIsDownloadedKey];
    NSNumber *downloading = [item valueForAttribute:NSMetadataUbiquitousItemIsDownloadingKey];
    NSNumber *uploaded = [item valueForAttribute:NSMetadataUbiquitousItemIsUploadedKey];
    NSNumber *uploading = [item valueForAttribute:NSMetadataUbiquitousItemIsUploadingKey];
    NSDate *createData = [item valueForAttribute:NSMetadataItemFSCreationDateKey];
    NSDate *updateDate = [item valueForAttribute:NSMetadataItemFSContentChangeDateKey];
    NSNumber *hasConflicts = [item valueForAttribute:NSMetadataUbiquitousItemHasUnresolvedConflictsKey];

    RMLogInfo(@"Metadata item name: %@, display: %@, path: %@, url: %@, ded: %@, ding: %@, ued:%@, uing: %@, created: %@, updated: %@, conflicts: %@", name, display, path, url, downloaded, downloading, uploaded, uploading, createData, updateDate, hasConflicts);
}

アップロードとダウンロードの割合を取得するためのキーもあります。

一度通知を処理したい場合は、ファイルがダウンロードされたことを確認できます。

于 2013-10-12T00:14:31.263 に答える