Question

i enabled iCloud UIDocument in my app, and i store document on the cloud, the document are packaged, for receive notification of update of the iCloud Document i'm doing this:

- (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");
            } }];

    }
}

to start all i call [self startQeury], the problem is that NSMetadataQueryDidUpdateNotification called a notification several time if i make a change in the document, how you can see the log:

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

as you can see here i make a change, and here below you can see that spawn 4 notification:

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

why is called several time? in my app i need to handle the change when the update is finish, so i need only one notification...how i can do?

EDIT: i have try what @rmaddy suggest in the answer, i have try this:

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");
            } }];
    }

but again i have the problem this is the log:

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

then i have edited a document and this is the log:

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

how i can do?

EDIT 2:

i have try with this:

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

and seems work, what you think? i can handle all time there is a change, or i can miss in this way some notification?

Was it helpful?

Solution

The notification is called for lots of reasons. When the file is first uploaded to iCloud and when the file is downloaded from iCloud. You also get updates about the percentage of upload and download. You can see all of these if you look at the various properties of the file.

I use a little debugging method to log each metadata item:

- (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);
}

There are also keys to get the percentage of upload and download.

If you want to handle the notification once, you can check that the file is downloaded.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top