自Mavericks以来,OS X在Finder中引入了标签。
我想知道是否有任何简单的方法来搜索具有给定标记的所有文件。 例如,获取用"收藏夹"标记的所有文件(可能在某个目录中)。 我知道我可以使用NSURL从单个文件中获取标签。使用它我可以通过迭代目录和文件来自己查询整个文件系统。 但我想知道Objective C API是否有更快的方法来实现它。
答案 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;。
我相信您可以进一步自定义查询以将其限制为目录。