N..
N..

Reputation: 125

NSMetadataQuery doesn't return any data

I try to list all of my file on my Mac for an app that I made. I use NSMetadataQuery but it's not working.

Here is the code:

import Cocoa

class ViewController: NSViewController
{

let metadataQuery = NSMetadataQuery()

@IBOutlet weak var searchTextField: NSTextField!

@IBOutlet weak var labelML: NSTextField!

@IBAction func searchClick(sender: AnyObject)
{
    labelML.stringValue = "Hello \(searchTextField.stringValue)!"
    startQuery()
    handleMetadataQueryFinished(metadataQuery)
}

override func viewDidLoad()
{
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}


func startQuery()
{
    print("Starting the query now...")

    metadataQuery.searchScopes = [NSMetadataQueryUbiquitousDataScope]
    let predicate = NSPredicate(format: "%K ==[cd] '*'", NSMetadataItemFSNameKey)

    metadataQuery.predicate = predicate
    if metadataQuery.startQuery(){
        print("Successfully started the query.")
    } else {
        print("Failed to start the query.")
    }

}

func handleMetadataQueryFinished(sender: NSMetadataQuery)
{

    print("Search finished");
    metadataQuery.disableUpdates()
    metadataQuery.stopQuery()
    print("Number of results \(metadataQuery.resultCount)")

    for item in metadataQuery.results as! [NSMetadataItem]
    {

        let itemName = item.valueForAttribute(NSMetadataItemFSNameKey)
            as! String

        let itemUrl = item.valueForAttribute(NSMetadataItemURLKey)
            as! NSURL

        let itemSize = item.valueForAttribute(NSMetadataItemFSSizeKey)
            as! Int
        print("Item name = \(itemName)")
        print("Item url = \(itemUrl)")
        print("Item size = \(itemSize)")

    }

    }

}

As you can see, I print the number of results of the metaQuery and it answers 0.

I've try to change some things like NSMetadataQueryIndexedLocalComputerScope instead of NSMetadataQueryUbiquitousDataScope or the format of the predicate but either way it's not working.

Any idea why?

Upvotes: 1

Views: 1111

Answers (1)

Daniel Bleisteiner
Daniel Bleisteiner

Reputation: 3310

You should register an observer for NSMetadataQueryDidFinishGatheringNotification and wait till its called. The search takes a little while. And did starting the query return true?

Here is some Objective-C style example from my code:

#import "CloudUtils.h"

@interface CloudUtils ()
@property(nonatomic, strong) NSMetadataQuery *query;
@end

@implementation CloudUtils

static CloudUtils *singleton;

+ (CloudUtils *) sharedInstance
{
    if (singleton == nil) {
        singleton = [[CloudUtils alloc] init];
    }
    return singleton;
}

+ (void) updateCloudDrive
{
    NSLog(@"in updateCloudDrive");

    CloudUtils *utils = [CloudUtils sharedInstance];

    // Wichtig: Das Query muss STRONG gebunden sein... sonst ist das zu früh wieder weg!
    utils.query              = [[NSMetadataQuery alloc] init];
    utils.query.searchScopes = [NSArray arrayWithObjects:NSMetadataQueryUbiquitousDocumentsScope, NSMetadataQueryUbiquitousDataScope,nil];
    utils.query.predicate    = [NSPredicate predicateWithFormat:@"%K like[cd] %@", NSMetadataItemFSNameKey, @"*"];

    [[NSNotificationCenter defaultCenter] addObserver:utils
                                             selector:@selector(queryDidFinishGathering:)
                                                 name:NSMetadataQueryDidFinishGatheringNotification
                                               object:utils.query];

    [[NSNotificationCenter defaultCenter] addObserver:utils
                                             selector:@selector(queryDidUpdate:)
                                                 name:NSMetadataQueryDidUpdateNotification
                                               object:utils.query];

    dispatch_async(dispatch_get_main_queue(), ^{
        // Das scheitert, falls schon ein solches Query läuft... was aber nicht schlimm ist.
        [utils.query startQuery];
    });
}

// Diese Methode kommt ins Spiel, wenn es zu viele Ergebnisse auf einmal sind...
// Dann werden einige davon schon gemeldet, bevor das Query ganz fertig ist...
- (void) queryDidUpdate: (NSNotification *) notification
{
    NSLog(@"in queryDidUpdate:");

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    NSError *error = nil;
    for (NSMetadataItem *item in [query results]) {
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
        NSLog(@"starting download of %@", url);
        [[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:url error:&error];
    }
    [query enableUpdates];
}

- (void) queryDidFinishGathering: (NSNotification *) notification
{
    NSLog(@"in queryDidFinishGathering:");

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidUpdateNotification          object:query];

    NSError *error = nil;
    for (NSMetadataItem *item in [query results]) {
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
        NSLog(@"starting download of %@", url);
        [[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:url error:&error];
    }
}

@end

Upvotes: 3

Related Questions