使用NSMetadataQuery和NSPredicate返回目录列表

n.e*_*ind 2 iphone objective-c nspredicate ios5 icloud

我正在尝试获取用户的iCloud文件夹中的目录列表.我找出了如何寻找特殊类型的文件(如txt文件),它工作正常:

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];
Run Code Online (Sandbox Code Playgroud)

但是,我现在只想获取目录.我已经阅读了有关NSPredicate的文档,但我不知道如何寻找目录.我想NSPredicate不是为此而做的?我可以检查是否有像这样的目录:

    BOOL isDir;
BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDir];
if (exists) {
    /* file exists */
    if (isDir) {
        /* file is a directory */
    }
 }
Run Code Online (Sandbox Code Playgroud)

但是如何将它应用于NSMetadataQuery,我不知道.如果能得到任何帮助,我将不胜感激.


编辑:

我将谓词改为 [NSPredicate predicateWithFormat:@"%K.pathExtension = ''", NSMetadataItemFSNameKey];

然后,我确定查询何时完成,如下所示:

    [[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

}
Run Code Online (Sandbox Code Playgroud)

最后,我做了一个计数,但是这总是会给我0但我在云端的目录很多(我通过Lion和Mobile Documents文件夹检查了这个;例如我有Documents/myTXTs等).这很奇怪.如果我对文本文件进行计数,它会给我4,因为我有4个txt文件.所以我想我的目录没有被计算在内:

 - (void)loadData:(NSMetadataQuery *)query {

    NSLog(@"Query count %i", [query resultCount]);

...
Run Code Online (Sandbox Code Playgroud)

nac*_*o4d 5

我没有运气就尝试过EmptyStack的答案....

我发现,NSMetadataQuery没有找到目录,这个问题是不是NSPredicate从结果是过滤目录,这个问题简直就是查询没有找到的文件夹.我已经尝试使用调试器,发现所有LBItem找到的,都是常规文件而不是目录.我希望Apple将来能够改进这一点. 也许在MountainLion这是更好的,因为他们似乎有文件夹支持...哎呀当然你没有在这里阅读,因为它仍然是NDA.算了吧

但是至少有一种方法可以解决这个问题:

例如,如果您的文件结构是;

|_Folder
| |_file
| |_file2
|_Folder1
| |_file
|_file
Run Code Online (Sandbox Code Playgroud)

我们使用谓词进行查询:

predicateWithFormat:@"%K LIKE '*'", NSMetadataItemFSNameKey
Run Code Online (Sandbox Code Playgroud)

结果将是(用于NSMetadataItemURLKey获取URL)

path/to/iCloud/Documents/Folder/file
path/to/iCloud/Documents/Folder/file2
path/to/iCloud/Documents/Folder1/file
path/to/iCloud/Documents/file
Run Code Online (Sandbox Code Playgroud)

我们需要做的是通过查看每个URL的组件数量并根据需要切断URL来自己过滤这些结果.第一级的项目应该有numberOfComponentsOfUbiquitousContainer + 1,下一级甚至还有一个,依此类推.我们也需要丢弃重复(或者像在这个例子中我们将得到Folder两次).

可能不是最佳但对我有用,

更新:

更好地使用下面的谓词,它会在抓取子文件夹时减少查询结果.

// 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];
Run Code Online (Sandbox Code Playgroud)