Представьте: на поддерживаемой старой версии iOS приложение падает только при открытии экрана с новой системной функцией. Как доказать, что причина — вызов API без проверки доступности ОС?
Нужно воспроизвести сбой на реальном устройстве со старой версией iOS, сопоставить стек падения с новым системным API и проверить все пути его вызова. Если API вызывается без проверки доступности версии ОС, а после добавления условной ветки со старым сценарием падение исчезает, причина подтверждена.
Мобильные приложения работают на нескольких версиях операционной системы одновременно, а системные API постепенно расширяются. Поэтому приложение может быть собрано с новым SDK, но запускаться на более старой версии iOS, где часть классов, методов или возможностей отсутствует.
Проверки доступности появились как механизм безопасного использования новых возможностей без немедленного отказа от поддержки старых систем. Они позволяют выбрать запасной сценарий вместо безусловного обращения к API, которого на устройстве может не быть.
Версия, с которой приложение собирается, и минимальная поддерживаемая версия iOS — разные параметры. Сборка с новым SDK не делает новый API доступным на старом устройстве.
Ошибка может проявляться только при открытии конкретного экрана, потому что проблемный код вызывается лениво. Последствиями бывают аварийное завершение, недоступность ключевого сценария и ложный вывод, что несовместимо само устройство, хотя фактическая причина — отсутствие проверки версии ОС.
Сначала фиксируют матрицу воспроизведения: модель устройства, версию iOS, сборку приложения, точный шаг до сбоя и наличие функции на этой версии ОС. Затем анализируют символы в стеке падения и проверяют, относится ли проблемный вызов к API, появившемуся в более новой версии.
Проверку нужно выполнять непосредственно перед использованием нового API и предусмотреть работоспособную ветку для старой системы. Например:
Важно проверять не только обработчик нажатия. Новый API может использоваться при создании экрана, инициализации свойства, регистрации наблюдателя, подготовке фоновой задачи или в коде, который выполняется раньше условной ветки. Проверка должна защищать каждый фактический путь обращения.
Есть два основных решения. Первое — добавить проверку доступности и fallback: это сохраняет поддержку старых систем, но увеличивает объём тестирования и может ограничить функциональность. Второе — повысить минимальную поддерживаемую версию iOS: реализация проще, но часть пользователей потеряет возможность установить или обновить приложение.
Проверка версии ОС не заменяет проверку возможностей устройства. Даже доступный на данной версии API может зависеть от аппаратной функции, поэтому для таких сценариев отдельно проверяют capability устройства. Также нужно убедиться, что запасной сценарий действительно функционален, а не просто предотвращает падение.
Команда добавила экран с системной функцией, доступной начиная с iOS 16, но минимальная версия приложения осталась iOS 15. На iOS 16 экран работал, а на iOS 15 приложение падало сразу после перехода к нему.
Рассматривались три варианта: поднять минимальную версию iOS, полностью скрыть функцию на старых системах или оставить экран с альтернативной реализацией. Повышение минимальной версии было самым дешёвым для разработки, но ухудшало охват; полное скрытие не устраивало продукт; альтернативная реализация требовала больше тестов.
Выбрали проверку доступности с упрощённым сценарием для iOS 15. Дополнительно проверили создание экрана, фоновые переходы и повторное открытие после возврата из другого приложения. В результате падение исчезло, а новая функция осталась доступной пользователям поддерживаемых новых систем.
Нет. Проблемный API может вызываться во время построения экрана, загрузки данных, инициализации объекта или восстановления состояния. Если объект создаётся до нажатия, приложение упадёт раньше, чем пользователь дойдёт до проверяемого обработчика. Нужно анализировать весь граф вызовов и тестировать холодный запуск, переход на экран, возврат из фона и повторное открытие.
Нет. Симулятор полезен для быстрой проверки ветвления и интерфейса, но не полностью заменяет физическое устройство. Реальное устройство выявляет различия в архитектуре, системных компонентах, доступных аппаратных возможностях, памяти и поведении конкретной версии ОС. Для подтверждения исправления нужен минимум один реальный поддерживаемый аппарат со старой системой.
Нет. Отсутствие падения — только технический критерий безопасности вызова. Нужно проверить понятный пользователю fallback: сообщение о недоступности, альтернативный сценарий или корректно ограниченный интерфейс. Иначе ошибка превращается из аварийного завершения в тихую потерю функциональности, которую сложнее обнаружить и диагностировать.