自定义Spotlight导入器和Finder的获取信息"更多信息"部分

Vin*_*nce 4 macos plugins cocoa metadata spotlight

我为我的应用程序定义的自定义文档类型编写了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>
Run Code Online (Sandbox Code Playgroud)

更多的事情,我的系统缺少mdcheckschema命令,但XML文件太短,我怀疑语法有问题.
有时,"更多信息"部分显示文件上次打开日期,有时没有.
最后,我尝试重新导入文件(mdimport),但无济于事.

我正在运行Mac OS X Moutain Lion 10.8.3,Xcode 4.6.2.

所以在这里我的问题是,我错过了在"更多信息"部分显示这些项目的内容吗?是否有人遇到过这样的问题并找到了解决方案?

编辑:

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

Mar*_*l42 10

我知道文斯可能很久就解决了这个问题(或者放弃了).但是,我花了很长时间来处理编写导入器的各种记录不完整或完全没有记录的问题,所以我想我会在这里记录我的发现.(我担心这已经变成了一篇文章 - 这是一个复杂的主题).

我们假设:

  • 您已经阅读了有关如何编写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不会从用户尚未打开的应用程序运行导入程序.

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

    没有正确宣布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>&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列出的属性. Resources/schema.plist.
    • 但是,如果要控制"获取信息"窗口中显示属性的顺序,则应列出要在displayattrs键中按所需顺序首先显示的属性.(例如,在模式中查看"public.movi​​e",它从其父"public.audiovisual-content"复制某些键,以便首先显示它们).
    • 您的架构必须在该attributes部分中定义至少一个自定义属性,并在allattrs键中引用它,否则Spotlight将忽略整个架构.如果您的导入器不提供任何自定义属性,那么只需向架构添加虚假自定义属性.(这个要求在Snow Leopard之后的某个时间到达并且完全没有记录,并且可能是Vince出错的地方).
    • 如果您的模式定义了一个自定义属性(它应该;请参阅上一点),那么您必须为其提供英语schema.strings本地化,否则Spotlight会忽略整个模式.(当然,欢迎您提供其他本地化).
    • 请您在您的Xcode项目副本有一个"复制包资源"阶段schema.xml,并schema.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中包含一个postinstall脚本:告诉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点.