سؤال

I'm trying to get my OS X app to update automatically from changes to an iCloud document, and I'm having a really hard time getting the notification to work. Specifically, I was given some code that should list out all the results of my NSMetadataQuery (just so I can do some testing and confirmation), but it's returning 0 results. This, despite the fact that clearly something is there in my ubiquity container because the data is being uploaded from my OS X app successfully, and downloaded again successfully at launch. Here's what I've got right now.

CloudDocument.h:

@property (nonatomic, strong) NSMetadataQuery *alertQuery;

CloudDocument.m:

@implementation CloudDocument

@synthesize alertQuery;

-(id)init {
    self = [super init];
    if (self) {
        alertQuery = [[NSMetadataQuery alloc] init];
        if (alertQuery) {
            // Search the Documents subdirectory only.
            [alertQuery setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];

            // Add a predicate for finding the documents.
            NSString *filePattern = @"*";
            [alertQuery setPredicate:[NSPredicate predicateWithFormat:@"%K LIKE %@", NSMetadataItemFSNameKey, filePattern]];
        }

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

        NSLog(@"Notification created");

        [alertQuery startQuery];
    }
    return self;
}

-(void)queryDidUpdate:(NSNotification *)notification {
    [alertQuery disableUpdates];

    NSLog(@"Something changed!!! - %@", [notification name]);

    // Look at each element returned by the search
    // - note it returns the entire list each time this method is called, NOT just the changes
    int resultCount = (int)[alertQuery resultCount];
    NSLog(@"%i", resultCount);
    for (int i = 0; i < resultCount; i++) {
        NSMetadataItem *item = [alertQuery resultAtIndex:i];
        [self logAllCloudStorageKeysForMetadataItem:item];
    }

    [alertQuery enableUpdates];
}

- (void)logAllCloudStorageKeysForMetadataItem:(NSMetadataItem *)item {
    NSLog(@"LogAll gets called");
    NSNumber *isUbiquitous = [item valueForAttribute:NSMetadataItemIsUbiquitousKey];
    NSNumber *hasUnresolvedConflicts = [item valueForAttribute:NSMetadataUbiquitousItemHasUnresolvedConflictsKey];
    NSNumber *isDownloaded = [item valueForAttribute:NSMetadataUbiquitousItemIsDownloadedKey];
    NSNumber *isDownloading = [item valueForAttribute:NSMetadataUbiquitousItemIsDownloadingKey];
    NSNumber *isUploaded = [item valueForAttribute:NSMetadataUbiquitousItemIsUploadedKey];
    NSNumber *isUploading = [item valueForAttribute:NSMetadataUbiquitousItemIsUploadingKey];
    NSNumber *percentDownloaded = [item valueForAttribute:NSMetadataUbiquitousItemPercentDownloadedKey];
    NSNumber *percentUploaded = [item valueForAttribute:NSMetadataUbiquitousItemPercentUploadedKey];
    NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

    BOOL documentExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];

    NSLog(@"isUbiquitous:%@ hasUnresolvedConflicts:%@ isDownloaded:%@ isDownloading:%@ isUploaded:%@ isUploading:%@ %%downloaded:%@ %%uploaded:%@ documentExists:%i - %@", isUbiquitous, hasUnresolvedConflicts, isDownloaded, isDownloading, isUploaded, isUploading, percentDownloaded, percentUploaded, documentExists, url);
}

-(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
    [Data setSyncProgressIndicators:NO];
    return [NSKeyedArchiver archivedDataWithRootObject:[Data getAllNotes]];
}

-(BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
    [Data setSyncProgressIndicators:YES];
    NSDictionary *dict = (NSDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)data];
    [Data didReceiveCloudData:dict];
    [Data setSyncProgressIndicators:NO];
    return YES;
}

+(BOOL)autosavesInPlace {
    return YES;
}

@end

The results that I'm seeing are that queryDidUpdate: gets called 2-3 times at launch, all from NSMetadataQueryDidFinishGatheringNotification. Thing is, the "resultCount" variable is always 0, so logAllCloudStorageKeysForMetadataItem never gets called, and NSMetadataQueryDidUpdateNotification never gets called at all, no matter how often I edit the cloud document.

Can anyone offer any advice about why the search is returning 0 results, despite the fact that there is clearly a file being synced back and forth? Or even better, can you see what's wrong with the code entirely, and what I can do to get NSMetadataQueryDidUpdateNotification on track and telling me when there have been edits to my file? I am saving the file, btw, using the method:

+(NSURL *)notesURL {
    NSURL *url = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    return [url URLByAppendingPathComponent:kAllNotes];
}

where "kAllNotes" = "notes".

Thank you in advance for your help!

EDIT: Note that when I say it's syncing successfully, it's not doing it because of the NSMetadataQuery. I've got a cloudDoc = [[CloudDocument alloc]initWithContentsOfURL:[self notesURL] ofType:NSPlainTextDocumentType error:nil]; line elsewhere that loads up the CloudDocument, so I know there's a document there and I know it's being changed by the iOS version of the app, but the NSMetadataQuery that I'm trying to master right now is only there to work with the NSMetadataQueryDidUpdateNotification, and none of that seems to be working correctly.

Also, I am definitely a beginner, so code snippets and examples when making suggestions are very, very much appreciated!

هل كانت مفيدة؟

المحلول

Alright, I found the answer: I've been saving my file to the root folder, but searching within NSMetadataQueryUbiquitousDocumentsScope. It should have been NSMetadataQueryUbiquitousDataScope, and now it seems to be working perfectly. I hope this helps people in the future!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top