【问题标题】:Objective C finder tags searchingObjective C finder 标签搜索
【发布时间】:2015-06-24 18:51:43
【问题描述】:

自 Mavericks 以来,OS X 在 Finder 中引入了标签。

我想知道是否有任何简单的方法可以搜索具有给定标签的所有文件。 例如,获取所有标记为“Favorite”的文件(可能在某个目录中)。 我知道我可以使用 NSURL 从单个文件中获取标签。使用它,我可以自己通过遍历目录和文件来查询整个文件系统。 但我想知道 Objective C API 是否有更快的方法来做到这一点。

【问题讨论】:

标签: objective-c macos tags osx-mavericks osx-yosemite


【解决方案1】:

谢谢@Volker。这让我走上了正确的道路。 (但只有在之后,我才花了三个小时编写一个框架,该框架将遍历每个文件,检查它是否与标记匹配,这是一种极其低效的方法。)

所以,这里有一个类,它将搜索并返回所有标有给定标签的文件。

FindTaggedFiles.h

@interface FindTaggedFiles : NSObject
{
    @private NSString* _tag;
    @private NSMetadataQuery* query;
}

-(id)initWithTag:(NSString*)tag withHandler:(void(^)(NSArray*))handler;
-(void)startSearch;
@end

FindTaggedFiles.m

@interface FindTaggedFiles()
@property (copy) void (^completionHandler)(NSArray*);
@end

@implementation FindTaggedFiles

-(id)initWithTag:(NSString *)tag withHandler:(void (^)(NSArray *))handler
{
    self = [super init];
    _completionHandler = handler;
    self->_tag = tag;
    return self;
}

-(void)startSearch
{
    query = [[NSMetadataQuery alloc]init];

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

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(initalGatherComplete:) name:NSMetadataQueryDidFinishGatheringNotification object:query];

    NSPredicate *searchPredicate;
    NSString* predicate = [NSString stringWithFormat:@"kMDItemUserTags == '%@'", self->_tag ];
    searchPredicate=[NSPredicate predicateWithFormat:predicate];
    [query setPredicate:searchPredicate];

    NSArray *searchScopes;
    searchScopes=[NSArray arrayWithObjects:NSMetadataQueryUserHomeScope,nil];
    [query setSearchScopes:searchScopes];

    NSSortDescriptor *sortKeys=[[NSSortDescriptor alloc] initWithKey:(id)kMDItemDisplayName ascending:YES];
    [query setSortDescriptors:[NSArray arrayWithObject:sortKeys]];

    [query startQuery];
}

- (void)queryDidUpdate:sender;
{
    NSLog(@"A data batch has been received");
}

- (void)initalGatherComplete:sender;
{
    [query stopQuery];

    NSMutableArray* files = [[NSMutableArray alloc]init];
    NSUInteger i=0;
    for (i=0; i < [query resultCount]; i++) {
        NSMetadataItem *theResult = [query resultAtIndex:i];
        [files addObject:theResult];
    }

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidUpdateNotification object:query];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    self->query=nil;

    _completionHandler(files);
}

那你就这样用吧

FindTaggedFiles* finder = [[FindTaggedFiles alloc]initWithTag:@"Disneyland" withHandler:^(NSArray* files){
    //do something with the files
}];

[finder startSearch];

NSMetaDataQuery 是异步工作的,所以我设计了这个类,在 init 方法中需要一个异步块作为处理程序代码。但是,在文档中,我相信它提到您不必异步运行搜索。

我的课是the code in the Apple documentation.的改编

另请注意:这不会在特定目录中搜​​索。元数据查询在特定的范围中运行。范围可以是用户的主目录(如本例所示)、用户的 iCloud、所有连接的驱动器以及其他几个。我在上面“限制搜索范围”下链接到的文档中涵盖了具体细节。

我相信您可以进一步自定义查询以将其限制为目录。

【讨论】:

  • 您的代码有一个问题:它在收到初始回调后停止查询。这并不好,因为我已经看到它发生了,特别是在搜索网络卷时,初始回调什么也不返回,但只有 queryDidUpdate: 回调会返回结果。
猜你喜欢
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
相关资源
最近更新 更多