Упрощенная разработка с меню только для отладки

Меню отладки в iOS - очень эффективный способ сделать ваш день разработчика более продуктивным. Если вы обнаруживаете, что выполняете одни и те же задачи отладки снова и снова, такие как печать ответов серверной части, переход к определенным контроллерам представления или копирование идентификаторов пользователей, было бы хорошо иметь в вашем приложении специальные меню разработчика, которые автоматически обрабатывают эти задачи за вас.

iOS 13 представила UIContextMenuInteraction, новый API контекстного меню, который заменяет старые (и гораздо более сложные в использовании) всплывающие меню. При нажатии UIView с зарегистрированным взаимодействием отображается меню, содержащее действия и необязательный предварительный просмотр. Он работает так же, как UIAlertController, но на него приятнее смотреть и его гораздо проще реализовать! В iOS 14 мы даже можем добавить к нему асинхронно разрешенные действия.

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

Пример: копирование данных зарегистрированного пользователя на монтажный стол

В этом примере представим, что у нас есть приложение, в котором нам часто приходится получать идентификатор пользователя зарегистрированной учетной записи. В прошлых проектах мне приходилось делать это много для целей отладки и сообщения об ошибках - либо чтобы сервер узнал, с каким пользователем у меня возникла проблема, либо чтобы иметь возможность вручную отправлять запросы к серверу в сервисе вроде Postman .

Обычно я делал это, устанавливая точку останова и распечатывая поля пользовательской модели, что было очень медленным и раздражающим процессом. Давайте добавим специальное меню отладки, которое сделает это за нас.

UIContextMenuInteraction работает через делегата. Чтобы меню отладки отображалось для представления, вы должны унаследовать делегата, определить список из UIActions, который должен отображаться, и вставить взаимодействие в представление. В этом случае мы добавим взаимодействие непосредственно в инициализатор.

Вот как выглядит наше «отлаживаемое пользовательское представление»:

Есть несколько способов удалить этот код из сборок выпуска, и я рекомендую использовать макросы препроцессора для полного устранения «кода отладки». Другие подходы по-прежнему позволят хакерам подвергнуть ваш код обратному проектированию.

#if DEBUG
extension UserTextField: UIContextMenuInteractionDelegate {
...
#endif

Расширение его для каждого UIView в приложении

Мы создали меню отладки для одного вида, но как насчет других? Как видите, этот код выглядит не очень красиво, и его довольно быстро станет сложно поддерживать. Чтобы исправить это, мы можем создать подкласс UIContextMenuInteraction в более чистую абстракцию, для которой требуется только список действий для отображения. Никаких настроек, превью или прочего надоедливого.

Я решил создать DebugMenuInteraction - специальный UIContextMenuInteraction, который обрабатывает свой собственный делегат, выставляя вместо этого DebugMenuInteractionDelegate для получения списка действий отладки:

Это позволяет нам преобразовать UserTextField в гораздо более чистую структуру:

Раньше взаимодействие добавлялось непосредственно в инициализатор класса. Это все еще можно сделать, но чтобы мы могли лучше отделить «код отладки» от производственного кода, мы можем вместо этого создать глобальное расширение:

Поскольку расширение само по себе может определить, запускаем ли мы отладочную сборку, вызовы addDebugMenuInteraction() можно сохранить в производственном коде, поскольку компилятор автоматически оптимизирует его вне сборки.

С этими абстракциями конечный результат тот же, но код теперь легче поддерживать и развивать, поскольку поддержка различных представлений - это просто вопрос их расширения для соответствия новому делегату.

iOS 14 - Асинхронные действия с UIDeferredMenuElement

С выходом iOS 14 появилась возможность создавать элементы меню, которые разрешаются асинхронно. Если ваши действия отладки включают некоторые данные, требующие вызова API, вы можете использовать новые API для создания асинхронных действий, которые автоматически отображаются в UIContextMenuInteraction со специальным пользовательским интерфейсом загрузки:

Тип завершения отложенного действия - это массив UIMenuElements, что означает, что одно действие может быть разрешено для нескольких записей в меню отладки. При отображении вы получите красивый экран загрузки, который заменяется реальными действиями после вызова обработчика завершения.

Заключение

Спасибо за прочтение. Если вы заинтересованы в создании меню отладки, код, который мы создали в этой статье, доступен в SPM и CocoaPods как библиотека DebugActions.