NSMetadataQuery未返回相关文件

移动开发 2026-07-10

我想用Spotlight来检索文件。它应该同时考虑文件名和文本内容。然而我得到的搜索结果与Finder中的结果或手动执行mdfind时的结果完全不同。下面的NSMetadataQuery只返回在浏览器缓存中匹配到的文件,而不是我主目录中的实际文件。问题出在哪里?

(附注:我已经通过entitlements禁用了应用沙箱。)

下面给出一个带固定搜索字符串的最小查询示例。

struct SpotlightSOExample: View {
    @State private var results: [String] = []
    @State private var query: NSMetadataQuery?
    @State private var token: NSObjectProtocol?

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            List(results, id: \.self) { path in
                Text(path)
            }
        }
        .onAppear(perform: runSearch)
    }

    private func runSearch() {
        results = []
        let query = NSMetadataQuery()
        query.searchScopes = [NSMetadataQueryUserHomeScope]
        query.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [
            NSPredicate(format: "kMDItemTextContent == %@", "*strom*"),
            NSPredicate(format: "kMDItemDisplayName CONTAINS[cd] %@", "strom"),
        ])
        query.valueListAttributes = [NSMetadataItemPathKey]

        token = NotificationCenter.default.addObserver(
            forName: .NSMetadataQueryDidFinishGathering,
            object: query, queue: .main
        ) { [self] _ in
            if let token { NotificationCenter.default.removeObserver(token) }
            query.disableUpdates()
            self.results = query.results.compactMap {
                ($0 as? NSMetadataItem)?.value(forAttribute: NSMetadataItemPathKey) as? String
            }
            query.stop()
            self.query = nil
            self.token = nil
        }

        query.start()
        self.query = query
    }
}

解决方案

这也让我很吃惊。我发现禁用应用沙箱是错误的。我知道这看起来有些违反直觉,但因为它们的特殊地位(在某种意义上,它们是“虚拟的”,因为它们“属于”iCloud Drive),桌面和文档是特殊的:NSMetadataQuery不会查询它们,除非应用沙箱处于启用状态。

完全不需要完整磁盘访问权限;你的说法在这点上是错的(这算是一个红鲱鱼)。只要开启沙箱,事情就会像你期望的那样工作。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章