使用NSMetadataQuery和NSPredicate返回目录列表 [英] Returning a list of directories with NSMetadataQuery and NSPredicate
问题描述
我正在尝试获取用户的iCloud文件夹中的目录列表。我找出了如何查找特殊类型的文件(如txt文件)并且工作正常:
I'm trying to get a list of directories in the user's iCloud folder. I worked out how to look for special types of files (such as txt files) and it works fine:
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
_query = query;
//Search all files in the Documents directories of the application’s iCloud container directories:
[query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K ENDSWITH '.txt'", NSMetadataItemFSNameKey];
[query setPredicate:pred];
[query startQuery];
但是,我现在只想获取目录。我已经阅读了有关 NSPredicate ,但我不知道如何寻找目录。我想NSPredicate不是为此而做的?我可以检查某个目录是否是这样的目录:
However, I'm now trying to get only directories. I've read through the docs concerning NSPredicate, but I have no clue how to go about looking for directories. I guess NSPredicate is not made for this? I can check if something is a directory like this:
BOOL isDir;
BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDir];
if (exists) {
/* file exists */
if (isDir) {
/* file is a directory */
}
}
但如何将此应用于NSMetadataQuery,我不知道。我很感激能得到任何帮助。
But how to apply this to a NSMetadataQuery, I have no clue. I'd be grateful for any help I can get.
编辑:
我将谓词更改为 [NSPredicate predicateWithFormat:@%K.pathExtension ='',NSMetadataItemFSNameKey];
然后我确定查询的时间完成如下:
I then determine when the query is finished like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query startQuery];
- (void)queryDidFinishGathering:(NSNotification *)notification {
NSMetadataQuery *query = [notification object];
[query disableUpdates]; // You should invoke this method before iterating over query results that could change due to live updates.
[query stopQuery]; // You would call this function to stop a query that is generating too many results to be useful but still want to access the available results.
[self loadData:query];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
_query = nil; // we're done with it
}
最后,我做一个计数,但这总是给我0在云中我有多个目录(我通过Lion和Mobile Documents文件夹检查了这个;例如我有Documents / myTXTs等)。这很奇怪。如果我对文本文件进行计数,它会给我4,因为我有4个txt文件。所以我想我的目录没有被计算在内:
And finally, I do a count, but this will always give me 0 however many directories I have in the cloud (I checked this via Lion and the Mobile Documents folder; e.g. I have Documents/myTXTs etc.). This is very strange. If I do a count on the text files, it will give me 4 as I have 4 txt files. So I guess my directories are not being counted:
- (void)loadData:(NSMetadataQuery *)query {
NSLog(@"Query count %i", [query resultCount]);
...
推荐答案
我没有运气就尝试过EmptyStack的答案....
I've tried EmptyStack's answer without luck....
我发现 NSMetadataQuery
找不到目录,问题不在于 NSPredicate
是从结果中过滤目录,问题只是查询找不到文件夹。我已经尝试使用调试器,发现找到的所有 LBItem
都是常规文件而不是目录。我希望Apple将来能够改进这一点。
也许在MountainLion中这是更好的,因为它们似乎有文件夹支持... oops当然你没有在这里阅读,因为它仍然是NDA。算了吧
I've found that NSMetadataQuery
does NOT find directories, The problem is not the NSPredicate
is filtering directories from the results, the problem is simply the query don't find folders. I've tried with the debugger and found that all LBItem
s found, are of regular files not directories. I hope Apple improves this in the future.
Maybe in MountainLion this is better since they seem to have folder support ... oops off course you didn't read this here because it's still NDA. Forget it
然而,至少有一种解决方法:
例如,如果您的文件结构是;
For example if your file structure is;
|_Folder
| |_file
| |_file2
|_Folder1
| |_file
|_file
我们使用谓词进行查询:
and we make a query with predicate:
predicateWithFormat:@"%K LIKE '*'", NSMetadataItemFSNameKey
结果将是(使用 NSMetadataItemURLKey
获取网址)
results will be (use NSMetadataItemURLKey
to get the URL)
path/to/iCloud/Documents/Folder/file
path/to/iCloud/Documents/Folder/file2
path/to/iCloud/Documents/Folder1/file
path/to/iCloud/Documents/file
我们需要做的是过滤这些结果由我们自己查看每个URL的组件数量并根据需要切断URL。第一级的项目应该有 numberOfComponentsOfUbiquitousContainer + 1
,下一级甚至还有一个,依此类推。
我们也需要丢弃重复(或者在本例中我们将获得文件夹
两次)。
What we need to do is to filter these results by ourselves by looking at the number of components of each URL and chopping URLs as needed. Items at the first level should have numberOfComponentsOfUbiquitousContainer + 1
, next level would have even one more and so on.
We need to discard repetitions too (or like in this example we will get Folder
twice).
可能不是最佳但对我有用,
Probably not optimal but works for me,
更好地使用下面的谓词,它会减少查询结果在抓取子文件夹时。
Better use below predicate, it reduce query results when crawling sub folders.
// dirPath is an NSString path of the directory you want
// to look at. Usually, for the top level directory:
// [NSFileManager URLForUbiquityContainerIdentifier:nil].path;
predicateWithFormat:@"%K BEGINSWITH %@", NSMetadataItemPathKey, dirPath];
这篇关于使用NSMetadataQuery和NSPredicate返回目录列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!