3

我正在尝试获取用户 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];

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

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

但是如何将此应用于 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

}

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

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

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

...
4

4 回答 4

7

我已经尝试了 EmptyStack 的答案,但没有运气......

我发现NSMetadataQuery找不到目录,问题不NSPredicate在于从结果中过滤目录,问题只是查询找不到文件夹。我已经尝试使用调试器,发现所有LBItem找到的 s 都是常规文件而不是目录。我希望苹果将来会改进这一点。 也许在 MountainLion 中这会更好,因为它们似乎支持文件夹……哎呀,你没有在这里读到这个,因为它仍然是 NDA。忘了它

但是,至少有一种解决方法:

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

|_Folder
| |_file
| |_file2
|_Folder1
| |_file
|_file

我们使用谓词进行查询:

predicateWithFormat:@"%K LIKE '*'", NSMetadataItemFSNameKey

结果将是(用于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

我们需要做的是通过查看每个 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];
于 2012-05-09T06:20:19.207 回答
2

如果您只想获取目录,请使用以下谓词。

predicateWithFormat:@"%K.pathExtension = ''", NSMetadataItemFSNameKey

请注意,这并不能保证您将使用此方法仅获取目录,因为存在(我已经看到一些)没有扩展名的文件。但是,如果您确定所有文件都有扩展名,那么您可以很好地使用它。

如果您想获取所有文件而不考虑其扩展名,只需在上述谓词中添加 NOT 关键字,

predicateWithFormat:@"NOT %K.pathExtension = ''", NSMetadataItemFSNameKey
于 2011-10-24T10:23:47.847 回答
0

您可以使用 MDQuery 执行此操作 - 这是 NSMetadataquery 使用的“真实”代码。

在终端中,输入“mdls”,然后拖入一个文件夹。然后键入 mdfind 并使用提供的示例仅将 kMDItemContentType 类型树更改为 public.folder - 您将获得很多结果。

然后要在代码中执行此操作,您需要遵循 MDQueryRef 示例。代码流与 Cocoa 的东西相同,我发现查询更容易创建和理解。您可以为 MDQuery 设置 cocoa 回调 - 因此它很好地兼容 NSMetadataquery。

NSMetadataQuery 有一些我认为在 MDQuery 中没有的 iCloud 内容。所以我认为它们并不相同。

于 2012-06-04T19:57:44.437 回答
-1

尝试这个:

[query setPredicate:[NSPredicate predicateWithFormat:@"%K like '*.txt'", NSMetadataItemFSNameKey]];

这个对我有用。

于 2011-10-28T08:20:51.303 回答