NSMetadataQueryDidFinishGatheringNotification 从未调用过

NSMetadataQueryDidFinishGatheringNotification never called

尝试运行以下代码:

#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;
}

出于某种原因,从未调用 NSMetadataQueryDidFinishGatheringNotification。

此外,NSMetadataQueryDidUpdateNotification 通知也从未被调用。

有人知道为什么吗? 有没有人对 Spotlight 搜索文件有更好的想法?

非常感谢!

当我进行一次修改时,您的代码可以在我的机器上运行。不要在循环中调用 sleep,而是调用 CFRunLoopRun():

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

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

    return 0;
}

通知机制是使用 运行 循环实现的,因此您必须有一个 运行ning 才能发挥它的魔力。