4

我为我的应用程序定义的自定义文档类型编写了一个 Spotlight Importer。

一切正常,元数据字段被 Spotlight 正确索引(使用mdls命令验证),Spotlight 搜索显示我的文档。

我遇到的唯一问题是,当我询问有关文件的信息(Finder 中的 Cmd+I)时,我在文件<displayattrs>部分中指定的项目未显示在“更多信息”部分中。schema.xml

我希望这些字段出现在那里,因为我在<allattrs><displayattrs>部分都声明了它们。

我在这里发现了几个与这个问题相关的问题,没有一个对我有帮助。

导入器被捆绑到应用程序中,由系统加载(mdimport -L确认这一点)。此外,bundle 结构似乎是正确的,它schema.xml出现在 Resources 文件夹以及schema.stringsen/lproj 文件夹中。

这是schema.xml文件的样子:

<schema version="1.0"
    xmlns="http://www.apple.com/metadata"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.apple.com/metadata file:///System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/MetadataSchema.xsd">
<types>
    <type name="com.mydomain.myapp.mydocument">
        <allattrs>
            kMDItemTitle kMDItemAuthors kMDItemAlbum
        </allattrs>
        <displayattrs>
            kMDItemTitle kMDItemAuthors kMDItemAlbum
        </displayattrs>
    </type>
</types>

还有几件事,我的系统缺少mdcheckschema命令,但是 XML 文件太短了,我怀疑语法有问题。
有时,“更多信息”部分会显示文件的上次打开日期,有时什么也不显示。
最后,我尝试重新导入文件(mdimport),但无济于事。

我正在运行 Mac OS X Moutain Lion 10.8.3、Xcode 4.6.2。

所以在这里我的问题是,我是否缺少将这些项目显示在“更多信息”部分中的内容?有没有人遇到过这样的问题并找到了解决方案?

编辑

到目前为止没有人回答我的问题,也许有人可以指点我一些关于这个问题的教程或文档?

4

1 回答 1

11

我知道文斯可能早就解决了这个问题(或放弃了)。但是我刚刚花了令人沮丧的很长时间来处理各种记录不充分或完全没有记录的问题,编写一个导入器,所以我想我会在这里记录我的发现。(恐怕这已经变成了一篇论文——这是一个复杂的主题)。

让我们假设:

  • 您已阅读有关如何编写 Spotlight 导入器的文档,尤其是故障排除指南。
  • 您已经编写并调试了您的导入器。

    要在 Xcode 中调试导入器,请选择 Product->Scheme->Edit Scheme 并设置:

    • 信息->可执行到/usr/bin/mdimport
    • 参数-> 参数-n -d2 -g $(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME) /path/to/some/test/file.ext
    • 选项->工作目录$(SRCROOT)

    并在 GetMetadataForURL() 函数上设置断点。

  • 正确的输出/usr/bin/mdimport -n -d2 -g /path/to/your/importer.mdimporter /path/to/some/test/file.ext包含您想要的标准和/或自定义元数据属性。
  • 您已经部署了您的导入器进行测试(在 /Library/Spotlight/ 中独立或嵌入在应用程序包中)并mdimport -L列出了您的导入器。
  • 但是mdls /some/other/file.ext和/或 Finder 的“获取信息”窗口的输出没有显示您期望的元数据属性。

这里有一些事情要检查:

  1. 其他人需要为您要导入的文档类型声明 UTI。

    • 如果您要导入系统声明类型的文档,那么 OSX 已经为您声明了 UTI。
    • 如果您的导入程序嵌入在应用程序包中,则应用程序应通过UTExportedTypeDeclarations应用程序的 Info.plist 中的键声明 UTI。
    • 如果您要导入第三方文档类型,请检查“拥有”该文档类型的应用程序是否已UTExportedTypeDeclarations在应用程序的 Info.plist 中的键中为其声明了 UTI。如果应用程序没有声明 UTI(有些没有并且仍然使用旧的CFBundleDocumentTypes->CFBundleTypeExtensions键),或者如果您希望导入器在未安装应用程序的情况下也能工作,那么您将不得不创建一个“虚拟”应用程序,其唯一目的是UTImportedTypeDeclarations在应用程序的 Info.plist 中的键中声明 UTI。在 /Library/Application Support/myOrg/myApp.app 之类的地方安装“虚拟”应用程序。您的导入器应该是独立的,并且不应嵌入到此应用程序的捆绑包中,因为 Spotlight 不会从用户尚未打开的应用程序运行导入器。

    声明您要导入的 UTIUTImportedTypeDeclarations或导入器的 Info.plist 中的键是没有意义UTExportedTypeDeclarations的 - LaunchServices 不会从那里可靠地读取它们,因此 Spotlight 不会识别它们。但是,您必须通过在您的进口商的 Info.plist 中的->键中引用它们来注册您对 UTI 的兴趣。CFBundleDocumentTypesLSItemContentTypes

    其他人没有正确声明尿路感染的症状是mdimport -n -d1 /some/file.ext

    • Imported '/some/file.ext' of type 'dyn.xxx' ...或(令人困惑):
    • Imported '/some/file.ext' of type 'the.correct.uti' with no plugIn.

    .

  2. 如果您的导入程序返回的属性未列在文档 UTI 或任何父 UTI 的元数据架构中,则Spotlight 会丢弃该属性。即使它是像 kMDItemAuthors 这样的标准属性。要了解原因,我们需要详细了解 Spotlight 的工作原理:

    • UTImportedTypeDeclarations应用程序在orUTExportedTypeDeclarations键中声明一个或多个 UTI 。
    • 在每个 UTI 声明中,应用程序在一个UTTypeConformsTo键中指定一个或多个“父”UTI。如果可能,父 UTI 应该是特定的 - 例如,如果应用程序声明了一种新型图像文件,则为“public.image” - 或者如果没有其他合适的,则只是“public.data”。

      • 您可以通过查看 LaunchServices 数据库的内容来查看 UTI 层次结构的当前状态/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -dump
      • 但这很难破译。幸运的是,您通常会对“干净”机器的 UTI 层次结构更感兴趣,可以通过plutil -p /System/Library/CoreServices/CoreTypes.bundle/Contents/Info.plist.
    • Spotlight 维护一个“模式”,其中列出了它感兴趣的元数据属性:

      • 您可以使用 来查看元数据模式的当前状态mdimport -X 2>&1
      • 您可以在 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/schema.plist 中看到“干净”机器的元数据模式。
    • 当 Spotlight 决定存储什么时,它会根据 UTI 层次结构和元数据模式交叉引用导入程序的输出。因此,对于您的进口商返回的每个属性:

      • Spotlight 在元数据模式中查找文档的 UTI。如果存在 UTI 条目,则 Spotlight 会检查您的导入程序返回的属性是否列在该allattrs键下。如果是,则 Spotlight 将您的进口商提供的值记录在其数据库中。
      • 否则,Spotlight 在 UTI 层次结构中查找父 UTI 并重复该过程,直到找到“public.data”。
      • 如果 Spotlight 找不到allattrs您文档的 UTI 或任何父 UTI 的键中列出的属性,那么它会丢弃您的导入器提供的值。

    .

  3. 如果存储在 Spotlight 数据库中的属性未列出以显示在文档 UTI 或任何父 UTI 的元数据架构中,则Finder 的“获取信息”窗口将不会显示它。即使它是像 kMDItemAuthors 这样的标准属性。

    • Finder 遵循与上述 Spotlight 类似的过程,不同之处在于它查询displayattrs键而不是allattrs元数据数据库中的键。
    • 属性的显示顺序取决于它们在元数据模式层次结构中的位置。

    .

  4. 如果您想控制 Spotlight 存储的内容和/或 Finder 的“获取信息”窗口显示的内容,那么您的导入器需要提供自定义架构。

    • 自定义 schema.xml 的格式有很好的文档记录。不幸的是mdcheckschema,文档中提到的命令不再随 Xcode 一起提供。如果您有一台装有旧版 OSX 和 Xcode 的机器,您可以从/usr/bin/mdcheckschema. 如果您有 Apple Developer 帐户,您可以从“Xcode 4.2 for Snow Leopard”dmg 上的 /Packages/DeveloperToolsCLI.pkg 中提取它。
    • 您不必在allattrsdisplayattrs键中列出导入程序支持的每个属性 - 只需列出 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/中未列出的父级或祖父级 UTI 的属性资源/schema.plist 。
    • 但是,如果您想控制属性在“获取信息”窗口中显示的顺序,您应该在键中以您希望的顺序列出您希望首先显示的属性displayattrs。(例如,请参见架构中的“public.movi​​e”,它复制了其父“public.audiovisual-content”中的一些键,以便首先显示它们)。
    • 您的架构必须在该部分中定义至少一个自定义属性attributes并在一个键中引用它allattrs,否则 Spotlight 会忽略整个架构。如果您的导入器不提供任何自定义属性,那么只需向架构添加一个虚假的自定义属性即可。(这个要求是在 Snow Leopard 之后的一段时间出现的,并且完全没有记录,这可能是 Vince 出错的地方)。
    • 如果您的架构定义了一个自定义属性(它应该;参见前一点),那么您必须为其提供英语 schema.strings 本地化,否则 Spotlight 会忽略整个架构。(当然也欢迎您提供其他本地化)。
    • 检查您的 Xcode 项目中是否有一个“复制捆绑资源”阶段,该阶段可以复制schema.xmlschema.strings进入您的产品。
    • 仔细检查您构建的产品中是否确实存在Contents/Resources/schema.xml 和 Contents/Resources/en.lproj/schema.strings 或 Contents/Resources/English.lproj/schema.strings ;一些旧版本的 Xcode 没有复制它们。
    • 检查file /path/to/your/built/importer.mdimporter/Contents/Resources/en.lproj/schema.strings说:
      • Little-endian UTF-16 Unicode c program text.

    出现上述任何错误的一个症状是,mdimport -X 2>&1 | grep -A20 uti.of.interest要么不返回任何内容,要么为导入器的 schema.xml 试图定义的 UTI 返回一个空架构。

  5. Spotlight 并不总是及时注意到变化。

    • 在测试导入器的更新版本时,首先删除旧导入器(或包含它的整个应用程序,如果它嵌入在应用程序包中)并键入mdimport -L以检查 Spotlight 是否注意到它已消失(这可能需要大约 30 秒),然后再部署您的更新后的版本。再次键入mdimport -L以检查 Spotlight 在恢复测试之前是否注意到了更新的版本(同样这可能需要大约 30 秒)。
    • 如果您在 .pkg 文件中分发独立的导入器,那么您应该在 1 中包含一个安装后脚本:告诉 LaunchServices 捆绑包已更新(安装程序会自动为应用程序执行此操作,但不会为其他捆绑包类型执行此操作)和 2:让 Spotlight 为当前用户重新索引您的进口商理解的文档类型:

      #!/bin/sh touch -c "$2" if [ -n "$USER" ]; then sudo -u "$USER" /usr/bin/mdimport -r "$2"; fi true

  6. LaunchServices 并不总能及时发现变化,并保留旧信息。

    • 如果您要更改声明它们的应用程序中的 UTI 声明,或者更改您的进口商注册的 UTI,那么 LaunchServices 和 Spotlight 可能会混淆。您可以完全重置 LaunchServices 并通过以下方式从标准位置重新读取它:

      /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -v -kill -seed -domain system -domain network -domain local -domain user

      如果您想在开发系统上模拟导入器和/或应用程序的“干净”安装,这也很有用。

编辑: gitHub 上的这个项目说明了上面的第 1-5 点。

于 2014-12-03T23:06:49.043 回答