При удалённой отладке приложения для работы с документами в macOS разработчики нередко сталкиваются с такой ситуацией: если явно указать приложение в Терминале, тестовый файл открывается, но двойной щелчок по тому же файлу на рабочем столе запускает другое приложение или вызывает запрос на выбор приложения. Успех в первом случае означает лишь то, что приложению можно передать файл; ассоциация типа файла при этом не проверена. Чтобы найти причину, нужно рассматривать объявление типа, обработку файла приложением и открытие по умолчанию как три отдельных результата.
В качестве примера возьмём пользовательский файл .notejson. Его содержимое — JSON, а расширение обозначает собственный формат документов приложения. Проверять нужно уже собранное и работающее приложение macOS. Тестовый файл должен содержать только вымышленные данные, а не рабочий документ.
Сначала объявите тип файла, а не просто проверяйте расширение
Собственному формату нужен постоянный идентификатор типа. В этом примере это dev.sample.notejson, расширение — notejson, а содержимое соответствует JSON. В настройках приложения необходимо сделать две вещи: экспортировать тип и объявить, что приложение умеет его открывать. Проверка расширения имени файла в коде сама по себе не создаст ассоциацию в Finder.
Настроив экспортируемый тип и Document Types в целевом приложении Xcode, проверьте Info.plist в собранном пакете приложения. У экспортируемого типа должны быть указаны идентификатор, расширение и родительский тип, которому он соответствует; тип документа должен ссылаться на тот же идентификатор. Если пример приложения позволяет только просматривать файлы, задайте для документа роль Viewer. Не заявляйте поддержку редактирования, которая ещё не реализована.
Проверять нужно собранный пакет приложения, а не настройки в интерфейсе проекта, которые могли не попасть в сборку.
Если формат на самом деле не является JSON, не объявляйте его соответствующим JSON только ради прохождения проверки. Связи типов должны отражать реальное содержимое. После изменения объявления пересоберите приложение: старый пакет не обновится сам при изменении настроек проекта.
Проверьте объявления в подготовленном пакете приложения
Сначала поместите приложение, которое предстоит проверить, по фиксированному пути. В командах ниже для примера используется /Applications/NoteReader.app. Перед запуском замените значение APP на путь к своему приложению:
APP="/Applications/NoteReader.app"
test -d "$APP/Contents" || exit 1
plutil -extract UTExportedTypeDeclarations json -o - "$APP/Contents/Info.plist"
plutil -extract CFBundleDocumentTypes json -o - "$APP/Contents/Info.plist"
В первом выводе проверьте наличие dev.sample.notejson и notejson, во втором — того же идентификатора типа и роли документа. Если plutil сообщает об отсутствии ключа, вернитесь к настройкам целевого приложения и результату сборки, не переходя сразу к проверке двойным щелчком. В некоторых проектах итоговый список свойств формируется из настроек сборки, поэтому ориентироваться особенно важно на файл внутри пакета.
На удалённом Mac также убедитесь, что проверяете именно только что собранный экземпляр. Если приложение с тем же именем осталось и в папке загрузок, и в папке приложений, проверка с явно указанным путём в Терминале и проверка открытия по умолчанию через Finder могут обратиться к разным копиям. Запишите путь к пакету и уберите старые копии, не участвующие в проверке: это полезнее, чем снова и снова менять объявления типов.
Разделите причины сбоя двумя способами открытия
Создайте временный тестовый файл. Сначала откройте его, явно указав приложение, затем проверьте выбор системы по умолчанию:
APP="/Applications/NoteReader.app"
CASE="$(mktemp -d)"
printf '{"title":"association-check"}\n' > "$CASE/demo.notejson"
open -a "$APP" "$CASE/demo.notejson"
open "$CASE/demo.notejson"
Успешный вызов open -a означает, что указанному приложению было предложено обработать файл. Затем обязательно проверьте, действительно ли приложение показывает содержимое тестового файла: одно лишь появление окна не доказывает, что файл прочитан. Во второй команде приложение не указано — именно она проверяет выбор при открытии по умолчанию. Можно также дважды щёлкнуть по тому же файлу в Finder и посмотреть, какое приложение откроется.
Ассоциация по умолчанию зависит от приложений, установленных на данном Mac, и выбора пользователя. Поэтому отдельно запишите «результат открытия с указанным приложением» и «результат открытия по умолчанию для текущего пользователя». Не считайте второй результат неизбежно одинаковым на всех машинах. Если система предлагает выбрать приложение, тоже зафиксируйте это, а не засчитывайте как успешную автоматическую ассоциацию.
Ищите причину по симптомам, не спешите менять код чтения
| Что наблюдается | Что проверить в первую очередь |
|---|---|
| В пакете приложения нет объявления типа или документа | Настройки целевого приложения и фактический результат сборки |
| Файл не читается даже при явном указании приложения | Содержимое файла, логику приёма и разбора файла в приложении |
| Указанное приложение читает файл, но по умолчанию он открывается в другом | Ассоциацию по умолчанию у текущего пользователя и другие копии приложения |
| Приложение запускается, но показывает пустой документ | Обработку ошибок после получения файла и состояние интерфейса |
Последние две ситуации особенно легко перепутать. После передачи файла приложению система уже выполнила свою часть работы, но приложение всё ещё может отказаться разбирать файл из-за ошибки в тестовых данных. И наоборот: приложение может безупречно разбирать файл, но система не обязательно выберет его по умолчанию. Сначала определите, на каком этапе возникает проблема, и только потом меняйте соответствующий код.
После проверки удалите временный тестовый файл. Сохраните в записи о сборке путь к пакету приложения, идентификатор типа, расширение тестового файла и результаты обоих способов открытия. При следующем изменении Info.plist или кода чтения документов повторите те же проверки. Так вы сможете понять, затронуло ли изменение ассоциацию типа или работу самого приложения, вместо того чтобы делать вывод на основании «однажды я открыл файл двойным щелчком».
Часто задаваемые вопросы
Почему двойной щелчок запускает другую программу, хотя open -a работает?
Параметр -a явно задаёт приложение и не проверяет выбор программы по умолчанию. Изучите объявление типа в пакете, затем откройте файл без -a или двойным щелчком.
Что проверять, если файл передан приложению, но его содержимое не читается?
Передача файла и разбор содержимого — разные этапы. Сначала проверьте фактический формат файла, затем код чтения и выдаваемую приложением ошибку.
Подключите облачный Mac к своему рабочему процессу
VPSPush предоставляет выделенные физические Mac с удалённым доступом. Выберите локацию и срок аренды, затем проверьте данные для подключения и итоговую сумму в заказе.