Take the 2-minute tour ×

I've been working on adding to my project (which is quite a pain in the buns) and I'm able to save and remove files, but I can't get a list of the files stored in iCloud. I've tried solutions from about 10 different websites (including the Apple documentation). Whenever I call [self.query startQuery]; everything seems to be working: The correct methods get called, the methods execute exactly as they should. Then when I ask for an of the files in my app's iCloud Documents directory I get two parenthesis with nothing between them (when I view in NSLog): File List: ( ). I know for a fact that there are many different documents of all shapes, extensions, sizes, and names in my app's iCloud Documents directory because I've been using the iCloud Developer site to check if things are working. My first method to setup the query is as follows:

- (void)syncWithCloud {
self.query = [[NSMetadataQuery alloc] init];
NSURL *mobileDocumentsDirectoryURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
[query setSearchScopes:[NSArray arrayWithObjects:NSMetadataQueryUbiquitousDocumentsScope, nil]];
//[query setPredicate:[NSPredicate predicateWithFormat:@"%K LIKE '*'", NSMetadataItemFSNameKey]];
[query setPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%%K like \"%@*\"", [mobileDocumentsDirectoryURL path]], NSMetadataItemPathKey]];

//Pull a list of all the Documents in The Cloud
[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(processFiles:)
                                             name:NSMetadataQueryDidFinishGatheringNotification object:self.query];
                                             name:NSMetadataQueryDidUpdateNotification object:self.query];

[self.query startQuery];

The process files method provided by Apple is next:

- (void)processFiles:(NSNotification*)aNotification {
    NSMutableArray *discoveredFiles = [NSMutableArray array];

    //Always disable updates while processing results.
    [query disableUpdates];

    //The query reports all files found, every time.
    NSArray *queryResults = [query results];
    for (NSMetadataItem *result in queryResults) {
        NSURL *fileURL = [result valueForAttribute:NSMetadataItemURLKey];
        NSNumber *aBool = nil;

        // Don't include hidden files.
        [fileURL getResourceValue:&aBool forKey:NSURLIsHiddenKey error:nil];
        if (aBool && ![aBool boolValue])
            [discoveredFiles addObject:fileURL];

    //Update the list of documents.
    [FileList removeAllObjects];
    [FileList addObjectsFromArray:discoveredFiles];
    //[self.tableView reloadData];

    //Reenable query updates.
    [query enableUpdates];

    NSLog(@"File List: %@", FileList);

Why doesn't this give me a list of files or at least some kind of data? Am I defining the NSMetadata query wrong, maybe my predicate isn't formatted right? I know I'm doing something wrong because there's no way iCloud could be this complicated (or could it?).
Thanks for the help in advance!

Edit #1: I am continuing to try different approaches to this problem. Using one of the answers below I have changed the predicate filter as follows:

[query setPredicate:[NSPredicate predicateWithFormat:@"NSMetadataItemFSNameKey LIKE '*'"]];

I have also added the following lines before the [query enableUpdates] call:

for (NSMetadataItem *item in query.results) {
        [FileList addObject:[item valueForAttribute:NSMetadataItemFSNameKey]];

In the processFiles method, I've tried placing all of the code on the background thread, but this makes no difference - as a matter of fact, when the code is not executed on the background thread FileList gives me this (null) instead of this ( ).

Could my problem have to do with thread management or memory allocation? Please note that I am using ARC.

Edit #2: The FileList variable is an NSMutableArray defined in my @interface and initialized in the -(id)init method before calling the processFiles method.

Edit #3: When testing my code with breakpoints I found that the following never gets run through - not even once. This leads me to believe that:
A. The proper directory isn't being connected with
B. iCloud can't see the files in the directory
C. My NSMetadataQuery isn't being setup properly D. Something completely different

Here's the code that starts the for-loop which never gets run:

NSArray *queryResults = [query results];
for (NSMetadataItem *result in queryResults) {
share|improve this question
add comment

2 Answers

Since you already set the search scope correct, there's no need to use special filters in the predicate. Just use:

query.predicate = [NSPredicate predicateWithFormat:@"NSMetadataItemFSNameKey == '*'"];

And to get the array use:

NSMutableArray *array = [NSMutableArray array];
for (NSMetadataItem *item in query.results) {
        [array addObject:[item valueForAttribute:NSMetadataItemFSNameKey]];
share|improve this answer
I'm still not getting any results with this. I've even tried moving the process off of the background queue, but all that does is make the result (null instead of ( ). Suggestions? Is it possible that my URLForUbiquityContainerIdentifier is not setup correctly? –  Sam Jan 1 '13 at 23:00
You don't need the NSURL above and therefore you don't the ContainerIdentifier. Have a look at the sample code from Erica Sadun's fine iOS cookbook. You'll want to examine the CloudHelper class. –  SAE Jan 1 '13 at 23:39
What exactly is FileList? From the naming convention it reads like a class, not like an object or variable. –  SAE Jan 2 '13 at 0:23
FileList is defined in the @interface section of my class like this: NSMutableArray *FileList;. And thanks for the link! –  Sam Jan 2 '13 at 0:41
And is FileList properly initialized before it is used in processFiles? –  SAE Jan 2 '13 at 1:07
show 2 more comments

I've solved my problem. Getting the list of files in iCloud was just a matter of correctly defining, allocating, and initializing properties. SAE's answer and this SO posting helped me solve my problem and create this GitHub Repo called iCloud Document Sync. The iCloud Document Sync class simplifies the whole iCloud Document storage process down to a few lines of code. The commit linked here fixes the issues from my question.

share|improve this answer
add comment

Your Answer


