Objective C finder标签搜索

时间:2015-04-17 18:57:52

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

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

Tagging a file

Searching for tags

我想知道是否有任何简单的方法来搜索具有给定标记的所有文件。 例如,获取用"收藏夹"标记的所有文件(可能在某个目录中)。 我知道我可以使用NSURL从单个文件中获取标签。使用它我可以通过迭代目录和文件来自己查询整个文件系统。 但我想知道Objective C API是否有更快的方法来实现它。

1 个答案:

答案 0 :(得分:0)

谢谢@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,所有连接的驱动器以及其他几个。我在上面链接的文档中详细介绍了#34;限制搜索范围&#34;。

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