Custom Spotlight Importer и раздел «Дополнительная информация» в Finder

Я написал Spotlight Importer для пользовательского типа документа, который определяет мое приложение.

Все работает нормально, поля метаданных правильно индексируются Spotlight (проверено с помощью команды mdls), а поиск Spotlight показывает мои документы.

Единственная проблема заключается в том, что элементы, которые я указываю в разделе <displayattrs> файла schema.xml, не отображаются в разделе «Дополнительная информация», когда я запрашиваю информацию о файле (Cmd+I в Finder).

Я ожидал, что эти поля появятся там, потому что я объявил их в секциях <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>

A couple of things more, my system is lacking the mdcheckschema command, but the XML file is so short, I doubt there is a problem with the syntax.
Sometimes, the "More Info" section display the file last opening date, sometimes nothing.
Finally, I tried reimporting the file (mdimport), to no avail.

Я использую Mac OS X Moutain Lion 10.8.3, Xcode 4.6.2.

Итак, вот мой вопрос: я что-то упустил, чтобы эти элементы отображались в разделе «Дополнительная информация»? Может кто сталкивался с такой проблемой и нашел решение?

Изменить :

Пока никто не ответил на мой вопрос, может быть, кто-нибудь может указать мне на какой-нибудь учебник или документацию по этой проблеме?


person Vince    schedule 03.05.2013    source источник


Ответы (1)


Я знаю, что Винс, вероятно, уже давно решил эту проблему (или сдался). Но я только что провел ужасно много времени, работая над различными плохо документированными или полностью недокументированными проблемами с написанием импортера, поэтому я решил задокументировать свои выводы здесь. (Боюсь, получилось эссе - сложная тема).

Предположим:

  • Вы прочитали документацию о том, как написать импортер Spotlight, в частности руководство по устранению неполадок.
  • Вы написали и отладили свой импортер.

    Для отладки импортера в Xcode выберите Product->Scheme->Edit Scheme и установите:

    • Info->Executable to /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 для типов документов, которые вы импортируете.

    • If you're importing a document of a system-declared type then OSX has declared the UTI for you.
    • Если ваш импортер встроен в пакет приложений, приложение должно объявить UTI с помощью ключа UTExportedTypeDeclarations в файле Info.plist приложения.
    • Если вы импортируете сторонний тип документа, убедитесь, что приложение, которое «владеет» этим типом документа, объявило для него UTI в ключе UTExportedTypeDeclarations в Info.plist приложения. Если приложение не объявило UTI (некоторые этого не делают и до сих пор используют вместо этого старый ключ CFBundleDocumentTypes->CFBundleTypeExtensions) или если вы хотите, чтобы ваш импортер работал, даже если приложение не установлено, вам придется создать " приложение-пустышка, единственная цель которого — объявить UTI в ключе UTImportedTypeDeclarations в файле Info.plist приложения. Установите «фиктивное» приложение куда-нибудь, например /Library/Application Support/myOrg/myApp.app. Ваш импортер должен быть автономным и не должен быть встроен в пакет этого приложения, поскольку Spotlight не будет запускать импортеры из приложения, которое пользователь не открывал.

    Нет смысла декларировать UTI, которые вы импортируете, в ключах UTImportedTypeDeclarations или UTExportedTypeDeclarations в файле Info.plist вашего импортера — LaunchServices не сможет надежно прочитать их оттуда, поэтому Spotlight не распознает их. Однако вы должны зарегистрировать свой интерес к UTI, ссылаясь на них в CFBundleDocumentTypes->LSItemContentTypes ключе (ах) в Info.plist вашего импортера.

    Признаки того, что кто-то другой неправильно объявил ИМП, заключаются в том, что 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:

    • An app declares one or more UTIs in a UTImportedTypeDeclarations or UTExportedTypeDeclarations key.
    • В каждом объявлении UTI приложение указывает один или несколько «родительских» UTI в ключе UTTypeConformsTo. Родительский UTI должен быть чем-то конкретным, если это возможно, например. «public.image», если приложение объявляет новый тип файла изображения, или просто «public.data», если ничего другого не подходит.

      • You can see the current state of the UTI hierarchy by poring over the contents of the LaunchServices database: /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -dump .
      • Но это сложно расшифровать. К счастью, обычно вас больше интересует иерархия UTI «чистой» машины, которую можно получить с помощью plutil -p /System/Library/CoreServices/CoreTypes.bundle/Contents/Info.plist .
    • Spotlight поддерживает «схему», в которой перечислены интересующие его атрибуты метаданных:

      • You can see the current state of the metadata schema with mdimport -X 2>&1 .
      • Вы можете увидеть схему метаданных «чистой» машины в /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/schema.plist .
    • Когда Spotlight решает, что хранить, он сверяет выходные данные вашего модуля импорта как с иерархией UTI, так и со схемой метаданных. Итак, для каждого атрибута, который возвращает ваш импортер:

      • Spotlight looks up the document's UTI in the metadata schema. If there exists an entry for the UTI then Spotlight checks whether the attribute that your importer returns is listed under the allattrs key. If it is then Spotlight records the value provided by your importer in its database.
      • В противном случае Spotlight ищет родительский UTI в иерархии UTI и повторяет процесс, пока не дойдет до «public.data».
      • Если Spotlight не может найти атрибут, указанный в ключе allattrs для UTI вашего документа или для любых родительских UTI, он отбрасывает значение, предоставленное вашим импортером.

    .

  3. Если атрибут, хранящийся в базе данных Spotlight, не указан для отображения в схеме метаданных для UTI вашего документа или для любых родительских UTI, то окно «Получить информацию» Finder не отобразит его. Даже если это стандартный атрибут, например kMDItemAuthors.

    • Finder follows a similar process to Spotlight above, except that it consults the displayattrs keys instead of the allattrs keys in the metadata database.
    • Порядок отображения атрибутов зависит от их положения в иерархии схемы метаданных.

    .

  4. Если вы хотите контролировать, что хранит Spotlight и/или что отображает окно Finder «Получить информацию», ваш импортер должен предоставить пользовательскую схему.

    • The format for the custom schema.xml is fairly well documented. Unfortunately the mdcheckschema command mentioned in the documentation no longer ships with Xcode. If you have a machine with an older version of OSX & Xcode you can copy it from /usr/bin/mdcheckschema. If you have an Apple Developer account you can extract it from /Packages/DeveloperToolsCLI.pkg on the "Xcode 4.2 for Snow Leopard" dmg.
    • Вам не нужно перечислять все атрибуты, которые поддерживает ваш импортер, в ключах allattrs и displayattrs — только те атрибуты, которые не указаны для UTI родительского или дедушки и прародителя в /System/Library/Frameworks/CoreServices .framework/Frameworks/Metadata.framework/Resources/schema.plist .
    • Однако, если вы хотите управлять порядком, в котором атрибуты отображаются в окне «Получить информацию», вы должны перечислить атрибуты, которые вы хотите отображать первыми в желаемом порядке в ключе displayattrs. (См., например, «public.movie» в схеме, которая дублирует некоторые ключи из родительского «public.audiovisual-content», чтобы они отображались первыми).
    • Ваша схема должна определять хотя бы один настраиваемый атрибут в разделе attributes и ссылаться на него в ключе allattrs, иначе Spotlight проигнорирует всю схему. Если ваш импортер не предоставляет никаких настраиваемых атрибутов, просто добавьте фиктивный настраиваемый атрибут в схему. (Это требование появилось через некоторое время после Snow Leopard и совершенно не задокументировано, и, вероятно, именно здесь Винс ошибся).
    • Если ваша схема определяет настраиваемый атрибут (а так и должно быть; см. предыдущий пункт), то вы должны указать для него английскую локализацию 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 не копировали их.
    • Check that file /path/to/your/built/importer.mdimporter/Contents/Resources/en.lproj/schema.strings says:
      • Little-endian UTF-16 Unicode c program text .

    Симптом неправильного выполнения любого из приведенных выше действий заключается в том, что mdimport -X 2>&1 | grep -A20 uti.of.interest либо ничего не возвращает, либо возвращает пустую схему для UTI, которую пытается определить ваш импортер schema.xml.

  5. Spotlight не всегда своевременно замечает изменения.

    • When testing an updated version of your importer first delete the old importer (or the entire app that contains it if it's embedded in an app bundle) and type mdimport -L to check that Spotlight has noticed that it's gone (this might take ~30s) before deploying your updated version. Type mdimport -L again to check that Spotlight has noticed the updated version (again this might take ~30s) before resuming testing.
    • Если вы распространяете автономный импортер в файле .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 выше.

person Marginal42    schedule 03.12.2014