NSMetadataQueryDidUpdateNotification вызывается несколько раз

Я включил iCloud UIDocument в моем приложении, и я храню документ в облаке, документ упакован, для получения уведомления об обновлении документа 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

как вы можете видеть здесь, я делаю изменение, а здесь ниже вы можете видеть это уведомление spawn 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

почему называется несколько раз? в моем приложении мне нужно обработать изменения, когда обновление закончится, поэтому мне нужно только одно уведомление... как я могу это сделать?

РЕДАКТИРОВАТЬ: я попробую то, что @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]) {
....
}

а кажется работа, что вы думаете? Я могу обрабатывать все время, когда есть изменения, или я могу пропустить таким образом некоторые уведомления?

1 ответ

Решение

Уведомление вызывается по многим причинам. Когда файл впервые загружается в 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);
}

Есть также ключи, чтобы получить процент загрузки и выгрузки.

Если вы хотите обработать уведомление один раз, вы можете проверить, что файл загружен.

Другие вопросы по тегам