Примечание, август 2026: этот пост относится к более раннему выпуску и описывает структуру тарифов на тот момент. В версии 1.2.0 AlcoLog объединил тариф Pro с Premium, так что теперь платный тариф один. При объединении ничего не потерялось, и все, у кого был Pro, перешли на Premium без доплаты.

Если ты вот-вот выпускаешь версию 1.0 приложения для iOS с подписками, встроенными покупками, компаньоном для часов, виджетами или любым позиционированием рядом со здоровьем, процесс App Review окажется тяжелее, чем следует из документации. Этот пост это разбор одного цикла запуска (четыре отказа за пять дней, пять рецензентов, одна и та же сборка) и тех закономерностей, благодаря которым цикл удалось пережить. Я делюсь этим, потому что такой опыт одна из наименее задокументированных частей выпуска серьёзного инди-приложения, а задокументированная версия (сессии WWDC, страница Review Guidelines, форумы разработчиков) не совпадает с повседневной реальностью.

Если ты посреди цикла и ищешь тактические исправления, переходи сразу к разделам «Что починить до отправки» и «Закономерности, которые стоит понимать». Личная хроника во второй половине, если нужен контекст.

# Что починить до отправки

Вот пункты, которые всплыли за четыре отказа. Если починить их заранее, ты убираешь основную часть поверхности для отказа у версии 1.0 в чувствительной категории с подписками.

# Иерархия отображения цены на экранах подписки

Human Interface Guidelines от Apple по подпискам однозначны в том, как показывать цену. Сумма списания должна быть самым заметным элементом цены. Маркетинговый инстинкт (сделать скидку главным выигрышем) здесь неверный. Инстинкт соответствия правилам (сделать типографским героем сумму списания) верный.

Что это значит на практике: обычная цена должна быть самой крупной и самой жирной. Вводная или скидочная цена меньше, с явной подписью «Первый период:». Избегай процентных бейджей в мелких значках (пиши «LAUNCH OFFER», а не «25% OFF»). Применение пункта 3.1.2© Payments and Subscriptions в этом месте одинаково у всех рецензентов.

# Явный путь удаления данных

Даже если твой «аккаунт» это всего лишь анонимный идентификатор, включаемый по согласию, пункт 5.1.1(v) от Apple требует подписанного, видимого и немедленного пути удаления. Выключение переключателя как неявное удаление кажется соответствующим со стороны разработчика, но не удовлетворяет нынешнему применению правил.

Заложи явную кнопку «Удалить мои данные» на экран приватности или настроек с первой же сборки. Добавь окно подтверждения. Убедись, что текст вокруг описывает реальное поведение при удалении, а не заглушку со сроками, которую ты собираешься переписать позже.

# Проверь Info.plist на рудиментарные объявления

Фоновые режимы, фоновая загрузка, права на геолокацию, объявления HealthKit и подобные записи в Info.plist могут месяцами лежать неиспользуемыми, пока код развивается. Их отмечают, когда они не совпадают с реальной функцией. Применение пункта 2.5.4 Software Requirements здесь механическое и однозначное.

Конкретно: любая запись в UIBackgroundModes должна соответствовать функции, которая её действительно использует. Если приложение объявляет «location» как фоновый режим, но ты никогда не используешь непрерывную фоновую геолокацию и у тебя allowsBackgroundLocationUpdates = false, убери объявление. Мониторинг регионов его не требует. Проверка занимает десять минут и предотвращает один цикл отказа.

# Работающая ссылка на Terms of Use в метаданных App Store

Поле Privacy Policy в App Store Connect известно всем. Требование по Terms of Use известно хуже. Если ты используешь стандартный EULA от Apple, включи ссылку на Terms of Use в описание приложения. Если у тебя свой EULA, добавь его в соответствующее поле App Store Connect.

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

# Видео App Preview: используй сырые записи экрана

Трёхмерные макеты телефонов, рамки устройств и стилизованные маркетинговые композиции это решения на усмотрение рецензента по пункту 2.3.4 Accurate Metadata. Публичная страница с рекомендациями прямо не запрещает рамки устройств, но внутренние обучающие материалы, по которым работают рецензенты, похоже, запрещают. Обычные записи экрана в родном разрешении безусловно безопасны.

Оставь маркетинговое оформление для собственного сайта, соцсетей и Reddit. В слот App Preview положи записи экрана. Разница в конверсии между «вылизанным макетом» и «сырой записью экрана» невелика. Снижение риска велико.

# Явная навигация к встроенным покупкам в App Review Notes

Рецензенты работают в бюджете от 5 до 15 минут на приложение. Они не всегда найдут каждую встроенную покупку, привязанную к версии. Если твои покупки доступны разными путями (отдельные экраны подписки, отдельные карточки, более глубокая навигация), добавь в App Review Notes пошаговые навигационные крошки для каждой покупки.

Работающий формат:

Premium subscriptions and Lifetime IAP: Settings tab > Premium card > Get Premium button > Premium upgrade sheet Pro subscriptions and Lifetime IAP: Settings tab > Pro card > Get Pro button Consumable Tip Jar items: Settings tab > scroll past tier cards > Tip Jar card > Show Tip Options

Звучит избыточно. Это предотвращает один конкретный цикл отказа (Guideline 2.1(b) Information Needed), который иначе стоит тебе дня.

# Календарный запас между отправкой и обещанной датой запуска

Для заявки на версию 1.0 с подписками в чувствительной категории закладывай минимум семь календарных дней между первой отправкой и датой запуска, которую ты назвал наружу. Каждый цикл отказа занимает примерно 24 часа, если отвечать оперативно. Четыре цикла отказа это реалистичный худший случай для версии 1.0 в чувствительной категории.

Если дата запуска обещана наружу (настроен предзаказ, запланировано In-App Event, куплен маркетинговый залп, разосланы питчи журналистам), семь дней запаса это минимум. Десять комфортнее. Всё, что меньше семи, рискует сорвать дату из-за одного процедурного отказа.

# Закономерности, которые стоит понимать

Несколько наблюдений изнутри цикла, которые неочевидны из документации.

# Каждый отказ находит разное

Четыре отказа вернулись с непересекающимися пунктами. У каждого рецензента был доступ ко всем экранам, которые предыдущий рецензент пропустил. Первый отметил ссылку EULA в метаданных. Второй отметил три разных пункта в той же сборке (фоновый режим, отображение цены, кнопка удаления). Третий отметил маркетинговый ассет. Четвёртый задал вопрос по навигации.

Это не баг. Это свойство того, как устроен App Review. Проверки, похоже, идут по проблемам, а не по приложению целиком. Рецензенты останавливаются на первой крупной проблеме, которую находят в своём бюджете времени. Они не обязаны проводить исчерпывающий аудит, и система не присваивает статус «уже проверено» тем поверхностям, которые пропустил предыдущий рецензент. Устройство работает на пропускную способность института, а не на удобство разработчика.

Вывод: невозможно получить полный аудит из одного прохода проверки. Ты получаешь только то, что вытащит текущий рецензент в своём окне времени, и приходится смириться с тем, что следующий может независимо вытащить что угодно ещё.

# Каждый следующий отказ обычно мельче предыдущего

Это нестрогая закономерность, а не гарантия. Первый отказ часто содержательный (не хватает требования, архитектурная проблема). Второй ещё содержательный, но уже больше похож на чек-лист. Третий уходит в периферийные метаданные. Четвёртый иногда вообще не отказ, а процедурный вопрос.

Причина не в том, что приложение «становится лучше» с каждым проходом. Причина в том, что проверяемая площадь в сборке и метаданных сжимается с каждым проходом: отмеченное чинится, а пропущенное больше не в фокусе. Рецензенты независимо вырабатывают доступную поверхность чек-листа, поэтому поздним проверкам достаётся меньше.

Эта закономерность успокаивает, пока ты в цикле, но не рассчитывай на неё. Поздний рецензент всё ещё может вытащить содержательный пункт, который пропустили ранние.

# Тщательность рецензентов различается драматически

За четыре проверки одной и той же сборки разброс в том, что находил каждый рецензент, был очень большим. Один нашёл три пункта. Другой один периферийный. Третий задал вопрос, ответ на который был в нажатии на карточку во второй вкладке приложения.

Ты никак не влияешь на то, какой рецензент получит твою заявку в конкретном проходе. Закладывай разброс. Не считай, что следующий проход будет тщательнее или мягче предыдущего. Это независимые выборки из широкого распределения.

# Одобрение в Beta App Review не предсказывает одобрение в полном App Review

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

Если ты используешь TestFlight, чтобы убедиться в готовности к продакшен-проверке, ты берёшь оттуда не тот сигнал. TestFlight ловит валидность сборки и базовые вопросы соответствия. Продакшен App Review ловит всю поверхность применения правил. Они не взаимозаменяемы.

# Векторы проверки в чувствительных категориях складываются

Подписки, особенно с вводными ценами или пробными периодами, автоматически включают проверку по 3.1.2. Категории рядом со здоровьем (алкоголь, фитнес, психическое здоровье, сон) включают внимание рецензента к 1.4.1 про медицинские заявления. Чувствительные к приватности функции (геолокация, HealthKit, анонимные идентификаторы) включают разбор по 5.1.1. Заявки на первую версию 1.0 включают комплексную проверку. In-App Events, привязанные к дате запуска, включают разбор метаданных.

Каждый вектор по отдельности управляем. Складываются они мультипликативно. Серьёзный запуск в чувствительной категории с подписками, несколькими платформами и In-App Event держит все векторы включёнными одновременно. Бесплатная утилита в один экран без покупок проходит за 2 минуты. Тяжесть твоей проверки коррелирует с серьёзностью и широтой твоего запуска, а не с качеством приложения.

# Документация и применение правил совпадают не всегда

В отказе может цитироваться указание, которого нет явно на связанной публичной странице. Рецензенты работают по внутренним обучающим материалам, которые пересекаются с публичными Review Guidelines, но не идентичны им. Если отказ не совпадает с публичной документацией, можно вежливо возразить. Иногда это разворачивают, иногда нет.

Возражая, делай это письменно в Resolution Center, структурированным абзацем, который цитирует публичное указание и просит назвать конкретный применяемый пункт. Убери из формулировок раздражение. Рецензент читает ответ в бюджете времени, и внимательно прочтут тот ответ, который этот бюджет уважает.

# Как конструктивно отвечать на отказы

Несколько практических заметок про переписку в Resolution Center.

# Отвечай в тот же день, если можешь

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

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

# Собери свои исправления в одну повторную отправку

Если отказ отмечает три пункта, почини все три до повторной отправки. Не отправляй ответ в духе «два из трёх готовы, третий в работе». Следующий рецензент вытащит совсем другие пункты, а частичное исправление просто добавит ещё один цикл в очередь.

# Прикладывай видеозапись проверки исправления

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

# Попроси в ответе комплексную проверку

Вежливая просьба поднять все оставшиеся вопросы разом в текущем проходе, а не растягивать их на дополнительные циклы, вполне уместна. Она не всегда срабатывает, но иногда срабатывает. Формулировка важна: «Мы оперативно и добросовестно устранили каждую поднятую проблему. Будем признательны за комплексную проверку по всем применимым рекомендациям в этом проходе, чтобы сократить дальнейшие циклы».

Это ставит рецензента в положение, где его следующий ответ либо пропускает приложение, либо вытаскивает все оставшиеся вопросы. Оба исхода лучше, чем ещё один отказ по одному пункту.

# Считай каждый проход независимым

Соблазн велик считать, что следующий рецензент прочитал заметки предыдущего. Скорее всего, нет. Каждый ответ в Resolution Center должен быть самодостаточным и подводить итог состоянию заявки для того, кто не видел прошлой переписки.

Значит, небольшое повторение между циклами необходимо. Подробные App Review Notes, сработавшие для первого рецензента, стоит приложить или пересказать и третьему. Не рассчитывай на институциональную память.

# Личная хроника

Для контекста вот как выглядели эти пять дней на самом деле.

Я отправил сборку 22 в субботу днём. В заявку входили 4 автопродлеваемые подписки, 2 непотребляемые пожизненные покупки, 5 потребляемых позиций Tip Jar, описание приложения, скриншоты, видео App Preview, In-App Event, привязанное к неделе запуска, и настроенный предзаказ на дату запуска в 175 странах.

Предыдущие шесть недель я систематически устранял всё, что мог предугадать. App Review Notes были написаны с дружелюбными к рецензенту пояснениями тех частей приложения, которые скорее всего привлекут внимание. Информация о трейдере по DSA была одобрена неделей раньше. Ярлыки App Privacy были опубликованы. Beta App Review пропустил несколько сборок. Я чувствовал себя готовым.

День 2, 5:15: первый отказ. Guideline 3.1.2©. В метаданных App Store нет работающей ссылки на Terms of Use. Исправление выпущено в тот же день (добавил ссылку на условия в экран апгрейда внутри приложения, расширил страницу условий, чтобы раскрыть все платные продукты, обновил описание приложения). Цикл в один день.

День 4, 16:03: второй отказ. Три пункта в одном сообщении. Guideline 2.5.4 (рудиментарная запись «location» в UIBackgroundModes, которой там быть не должно). Guideline 3.1.2© (вводная цена показана заметнее суммы списания). Guideline 5.1.1(v) (выключение переключателя анонимного идентификатора требовало явной подписанной кнопки удаления). Исправление выпущено в тот же день (убрал запись из Info.plist, перевернул иерархию цен, добавил явную кнопку «Удалить анонимные данные» с окном подтверждения). Цикл в один день.

День 5, 17:05: третий отказ. Guideline 2.3.4 Accurate Metadata. В видео App Preview были трёхмерные макеты телефонов, демонстрирующие экраны приложения. В заметке рецензента говорилось о содержимом, которое недостаточно показывает приложение в работе, и отдельно упоминались рамки устройств.

Сложность: публичная страница с рекомендациями на developer.apple.com/app-store/app-previews/ прямо не запрещает рамки устройств. Ближайшее задокументированное правило это «оставайся внутри приложения» с примерами про съёмку из-за плеча и физическое взаимодействие с устройствами. Ни то, ни другое не подходило.

До запуска оставалось четыре дня, накопленная задержка уже была четырёхдневной, и я сделал выбор. Убрал видео App Preview, чтобы разблокировать повторную отправку. Вежливо попросил пересмотреть решение, если есть конкретный пункт, который я упустил. Отправил вежливый структурированный абзац с просьбой поднять все оставшиеся вопросы разом в этом проходе. Удаление App Preview осталось в силе. На просьбу о пересмотре прямого ответа не пришло.

День 6, 19:23: четвёртое сообщение. Guideline 2.1(b) Information Needed. Формально не отказ. Пауза в проверке, чтобы задать вопрос. Рецензент не смог найти две встроенные покупки, привязанные к версии, и спросил, где они.

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

День 7, 20:30: одобрение. Сборка прошла. Предзаказ активирован. Неделя запуска назначена на 11 мая.

Пять дней были напряжёнными. Задним числом ни один из них не был экзистенциальным, хотя посреди цикла это ощущалось иначе. Накопленная задержка почти стоила даты запуска, но не стоила. Итоговый продукт ровно тот, что был собран до отправки. Ничего не вырезали, не меняли и не откладывали ради прохождения проверки.

# То, что цикл не отметил, тоже говорит о многом

За четыре проверки ни разу не отметили те поверхности, о которых я больше всего беспокоился.

Функция оценки привычек (оценка от 0 до 100 с помощниками и вредителями по шести взвешенным столпам). Поверхность учёта лекарств (только запись, без каких-либо рекомендаций). Модель приватности (без аккаунтов, данные на устройстве, анонимный обмен по согласию с явным удалением). Записи в HealthKit. Ни одну из этих поверхностей, то есть те части приложения, которые скорее всего вызвали бы вопросы про заявления о здоровье или про приватность, не отметили ни в одной из четырёх проверок. Четыре независимых рецензента посмотрели и все решили их не отмечать.

Вывод для тех, кто строит в чувствительных категориях: работа по проактивному раскрытию имеет значение. App Review Notes, объясняющие методику, оговорки внутри приложения, аккуратный выбор названий, консервативные формулировки в описании. Ничто из этого не выглядит эффектно. Всё это внесло вклад в то, что четыре рецензента подряд решили не отмечать самые спорные поверхности. Возрастной рейтинг 18+, экран с оговоркой при первом запуске, явный текст «мы не даём медицинских советов» в нужных местах. Всё это сработало.

Отметили же процедурную и механическую площадь. Иерархию отображения цены. Объявления фоновых режимов. Наличие ссылки в метаданных. Композицию маркетинговых ассетов. Обнаруживаемость встроенных покупок. Содержательные части приложения прошли каждый проход.

# Заключительные заметки для инди-разработчиков

Несколько наблюдений, которые не легли аккуратно выше.

Дешёвые приложения, которые ты видишь в App Store, не получают более мягкого обращения. Их одобрили годы назад, когда планка была ниже, или они не включают те векторы разбора, которые включает твой серьёзный запуск. Система награждает малозатратные и малорисковые приложения низким уровнем разбора. Твои усилия и внимательность часть причины, по которой твоя проверка тяжелее. Это не оценка качества твоего приложения.

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

Документирование инди-опыта в итоге сдвигает систему. За последнее десятилетие Apple заметно улучшила App Review. Часть этого улучшения тянется к тому, что инди-разработчики последовательно описывали свой опыт и совокупное давление росло. Твой конкретный отказ не приведёт к переобучению конкретного рецензента. Структурированная совокупность инди-опыта со временем сдвигает институциональную поверхность.

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

Если ты прямо сейчас посреди цикла и не спишь ночами в Resolution Center: запуск состоится. Продолжай отвечать. Система не про тебя лично. Продукт твой.


Этот пост документирует запуск AlcoLog, приложения для учёта выпитого на iOS. AlcoLog выходит в App Store 11 мая 2026 года, после описанного выше цикла. Приложение бесплатное, с необязательными тарифами Premium, и уже доступно для предзаказа в 175 странах.

Если ты разработчик под iOS и хочешь сверить заметки об опыте с App Review, сообщество инди-разработчиков на r/iOSProgramming и Indie Hackers хорошие места для начала. Чем конкретнее каждый из нас описывает то, с чем столкнулся, тем полезнее становится общая картина для следующего.