【问题标题】:Custom Spotlight Importer and Finder's Get Info "More Info" section自定义 Spotlight 导入器和 Finder 的获取信息“更多信息”部分
【发布时间】:2013-04-27 13:40:32
【问题描述】:

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

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

我遇到的唯一问题是,当我询问有关文件的信息时(在查找器)。

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

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

导入器被捆绑到应用程序中,由系统加载(mdimport -L 确认了这一点)。 此外,捆绑结构似乎正确,schema.xml 出现在 Resources 文件夹中,schema.strings 出现在 en/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。

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

编辑

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

【问题讨论】:

    标签: macos cocoa plugins metadata spotlight


    【解决方案1】:

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

    假设:

    • 您已阅读documentation,了解如何编写 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。

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

      没有意义声明您在导入器的 Info.plist 中的 UTImportedTypeDeclarationsUTExportedTypeDeclarations 键中导入的 UTI - LaunchServices 不会从那里可靠地读取它们,所以Spotlight 无法识别它们。但是,您必须通过在进口商的 Info.plist 中的 CFBundleDocumentTypes->LSItemContentTypes 键中引用来注册您对 UTI 的兴趣。

      其他人没有正确声明 UTI 的症状是 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 的工作原理:

      • 应用在UTImportedTypeDeclarationsUTExportedTypeDeclarations 键中声明一个或多个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&gt;&amp;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 找不到您文档的 UTI 或任何父 UTI 的 allattrs 键中列出的属性,则它会丢弃您的导入器提供的值。

      .

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

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

      .

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

      • 自定义schema.xml 的格式有很好的文档记录。不幸的是,文档中提到的mdcheckschema 命令不再随 Xcode 一起提供。如果您有一台装有旧版 OSX 和 Xcode 的机器,您可以从 /usr/bin/mdcheckschema 复制它。如果您有 Apple 开发者帐户,您可以从“Xcode 4.2 for Snow Leopard”dmg 上的 /Packages/DeveloperToolsCLI.pkg 中提取它。
      • 您不必在 allattrsdisplayattrs 键中列出您的导入器支持的所有属性 - 只需在 / System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/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&gt;&amp;1 | grep -A20 uti.of.interest 要么不返回任何内容,要么为导入器的 schema.xml 试图定义的 UTI 返回一个空架构。

    5. Spotlight 并不总是及时发现变化。

      • 在测试导入器的更新版本时,首先删除旧导入器(或包含它的整个应用程序,如果它嵌入在应用程序包中)并键入 mdimport -L 以检查 Spotlight 是否注意到它已消失(这可能需要~30s) 在部署更新版本之前。再次输入 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 上的This project 说明了上面的第 1-5 点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-31
      • 2020-06-30
      • 2013-07-07
      • 2014-01-06
      • 1970-01-01
      • 2013-10-11
      • 2016-12-31
      • 2011-01-05
      相关资源
      最近更新 更多