NSMetadataQueryDidFinishGatheringNotification never called

284 views Asked by At

Trying to run the following code:

#import <Foundation/Foundation.h>

@interface FileQuery : NSObject

@end

@interface FileQuery()

@property (nonatomic, strong) NSMetadataQuery *query;
@property (nonatomic, strong) NSMutableArray<NSURL *> *fileArray;

@end

@implementation FileQuery

-(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;
    _fileArray = nil;
  }
}

-(BOOL)startQuery:(NSString *)suffix {
  [_query stopQuery];

  dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(processFiles:)
                                                 name:NSMetadataQueryDidFinishGatheringNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(processFiles:)
                                                 name:NSMetadataQueryDidUpdateNotification
                                               object:nil];

    _query = [NSMetadataQuery new];
    if (_query) {
      NSLog(@"aa");
      _fileArray = [NSMutableArray new];
      [_query setSearchScopes:@[NSMetadataQueryLocalComputerScope]];
      [_query setPredicate:[NSPredicate predicateWithFormat:@"%K BEGINSWITH %@",
                            NSMetadataItemFSNameKey, suffix]];
      dispatch_async(dispatch_get_main_queue(), ^{
        if ([_query startQuery]) {
          [_query enableUpdates];
          NSLog(@"Finished with query = %@, predicate = %@", _query, _query.predicate);
        }
      });
    }
  });

  NSLog(@"bb");
  return TRUE;
}

- (void)processFiles:(NSNotification *)notification {
  [_query disableUpdates];

  // The query reports all files found, every time.
  NSArray * queryResults = [_query results];
  NSLog(@"Results = %@", queryResults);
  for (NSMetadataItem * result in queryResults) {
    NSURL * fileURL = [result valueForAttribute:NSMetadataItemURLKey];

    NSLog(@"file = %@", fileURL);
    [_fileArray addObject:fileURL];
  }

  [self stopQuery];
}

@end

int main(int argc, char *argv[]) {
  if (argc != 2) {
    NSLog(@"Error in number of params");
    return 0;
  }

  NSString *s = [NSString stringWithFormat:@"%s", argv[1]];
  NSLog(@"suffix = %@", s);

  FileQuery *q = [FileQuery new];

  if ([q startQuery:s]) {
    while(true) {
      NSLog(@"1");
      sleep(100);
    }
  } else {
    NSLog(@"query failed");
  }

  return 0;
}

For some reason, the NSMetadataQueryDidFinishGatheringNotification is never called.

Also, the NSMetadataQueryDidUpdateNotification notification is also never called.

Anyone has any idea as to why? Does anyone has any better idea for Spotlight search of files?

Thank you very much!

1

There are 1 answers

0
Charles Srstka On BEST ANSWER

Your code works on my machine, when I make one modification. Instead of calling sleep in a loop, call CFRunLoopRun():

int main(int argc, char *argv[]) {
    ...

    if ([q startQuery:s]) {
        CFRunLoopRun();
    } else {
        NSLog(@"query failed");
    }

    return 0;
}

The notification mechanism is implemented using the run loop, so you have to have one running for it to do its magic.