Вопросы для собеседования iOS-разработчика
Готовый набор для интервьюера: 36 вопросов с тезисами эталонного ответа, задача, рубрика и план встречи.
На собеседовании iOS-разработчика хорошо работает схема на 60 минут: 3-4 устных вопроса по стеку, одна задача на live coding, проектирование для middle и выше и вопросы кандидата. Ниже вопросы по грейдам из базы Техпрогона: у каждого тезисы, которые должен назвать сильный кандидат.
Всего в базе по этой роли 166 устных вопросов с чек-листом ответа.
Как построить техсобес на 60 минут
0-5 мин
Знакомство
Кто вы, формат встречи, кандидат коротко о себе и последнем проекте.
5-20 мин
Вопросы по стеку
3-4 устных вопроса из набора ниже. Сверяйте ответ с тезисами.
20-45 мин
Live coding
Одна задача. Смотрите на процесс по рубрике, а не только на ответ.
45-55 мин
Проектирование
Для middle и выше: система или решение целиком. Для junior: ещё вопросы.
55-60 мин
Вопросы кандидата
Что спросил кандидат, тоже сигнал: интерес к задачам и команде.
Junior: 12 вопросов
Основы: как устроено и зачем. Хватит 3-4 вопросов на встречу.
Как вы выбираете между Array, Set и Dictionary? Приведите примеры из iOS-приложения.
Что хотим услышать
- Array: порядок и доступ по индексу,
containsO(n) - Set: уникальность и проверка членства O(1), порядок не гарантирован
- Dictionary: поиск по ключу O(1), ключ
Hashable - Все три типы значений с copy-on-write
- Пример: лента в Array, id прочитанных в Set, кеш по URL в Dictionary
Если ответил, копните глубже
hash(into:) плохой?Объясни, как ты оцениваешь временную и пространственную сложность своего решения на собесе.
Что хотим услышать
- Называет, что такое n (и m, если входов несколько)
- Считает циклы: вложенные перемножаются, последовательные складываются
- Помнит скрытые циклы: includes, indexOf, slice, sort, spread
- Отдельно оценивает память, включая стек рекурсии
- Сравнивает с ограничениями: при n до 10⁵ O(n²) уже не годится
Если ответил, копните глубже
arr.slice() внутри цикла?Объясни, что такое CORS и как он работает.
Что хотим услышать
- Same-origin policy: скрипт не может читать ответы другого origin (схема, хост, порт)
- CORS: сервер заголовками
Access-Control-Allow-*разрешает конкретным origin читать ответы - Проверяет браузер, сервер отвечает всегда; вне браузера CORS не действует
- Простые запросы уходят сразу, остальные после preflight OPTIONS
- С куками нужен
credentials: 'include',Allow-Credentials: trueи точный origin вместо*
Если ответил, копните глубже
Объясни, зачем фронтенд-проекту сборщик и что происходит с кодом от исходников до файлов в dist.
Что хотим услышать
- граф зависимостей от точки входа
- трансформация: TS, JSX, современный синтаксис, CSS
- резолв пакетов из node_modules
- склейка в чанки, минификация, tree shaking
- хеши в именах для долгого кеша
- dev-сервер с HMR и source maps
Если ответил, копните глубже
Назовите ваши сильные стороны.
Что хотим услышать
- Две-три стороны, а не список из десяти
- Каждая подкреплена примером
- Стороны связаны с вакансией
- Нет пустых слов вроде «стрессоустойчивый, коммуникабельный» без доказательств
- Уверенно, без хвастовства
Если ответил, копните глубже
Расскажите, что такое опционал и как вы с ним работаете.
Что хотим услышать
- Optional это enum с кейсами
.noneи.some(Wrapped),T?сахар - Безопасная распаковка:
if let,guard let,??, опциональная цепочка !и IUO падают наnil, уместны редко (аутлеты, гарантированные инварианты)map,flatMap,compactMapдля преобразований без распаковки- Опционал делает отсутствие значения частью типа и проверяется компилятором
Если ответил, копните глубже
!?Объясни подход к задаче «найти два числа с суммой target» и его сложность.
Что хотим услышать
- Сначала называет перебор O(n²) как базовое решение
- Идея: для x ищем дополнение target - x в Map
- Проверяет Map до вставки x, чтобы не взять один элемент дважды
- Сложность O(n) времени и O(n) памяти
- Упоминает краевые случаи: дубликаты, нет ответа
Если ответил, копните глубже
Чем отличаются GET и POST? Ответ «у POST есть тело» не засчитывается.
Что хотим услышать
- GET читает и безопасен, POST меняет состояние
- GET идемпотентен, POST нет: его нельзя молча повторять
- GET кешируется браузером и прокси, POST по умолчанию нет
- Параметры GET в URL: попадают в логи и историю, длина ограничена серверами
- GET можно добавить в закладки и prefetch, поэтому нельзя менять данные по GET
Если ответил, копните глубже
Зачем разработчику Docker Compose и как ты его используешь?
Что хотим услышать
- Поднять зависимости одной командой: база, Redis, очередь
- Одинаковые версии сервисов у всей команды и в CI
- Сервисы общаются по именам в общей сети
- Тома для данных базы, bind mount для кода
- healthcheck и depends_on с condition для порядка старта
Если ответил, копните глубже
Какие у вас слабые стороны?
Что хотим услышать
- Назвал реальную слабость, а не штамп
- Слабость не критична для роли
- Рассказал, что делает, чтобы её компенсировать
- Есть пример прогресса
- Коротко, без самобичевания
Если ответил, копните глубже
Расскажите жизненный цикл UIViewController и что вы делаете в каждом методе.
Что хотим услышать
loadViewсоздаёт иерархию, переопределяют для кастомной корневой viewviewDidLoadодин раз: настройка UI, подписки, первичная загрузкаviewWillAppear/viewDidAppearпри каждом показе: обновить данные, аналитика, анимацииviewWillLayoutSubviews/viewDidLayoutSubviews: ручные расчёты фреймовviewWillDisappear/viewDidDisappear: остановить таймеры, сохранить состояниеdeinitпроверяет, что нет утечек
Если ответил, копните глубже
viewIsAppearing?Объясни, как слить пересекающиеся интервалы, и какая сложность.
Что хотим услышать
- Сортирует по началу и объясняет зачем
- Сравнивает только с последним интервалом в ответе
- Берёт максимум концов при слиянии
- Уточняет, считаются ли касающиеся пересекающимися
- O(n log n) времени, O(n) памяти на ответ
Если ответил, копните глубже
Middle: 12 вопросов
Практика: почему так, какие компромиссы, что ломается.
Где на практике возникают циклы сильных ссылок и как вы их находите и исправляете?
Что хотим услышать
- ARC не собирает циклы,
deinitне вызывается - Источники: делегаты, замыкания в свойствах, таймеры, наблюдатели, подписки Combine
- Лечение:
weakдля обратных ссылок,[weak self]в escaping-замыканиях,invalidate/отписка - Поиск: Memory Graph Debugger, Instruments, лог в
deinit - Тест на утечку: слабая ссылка на объект после теста должна стать
nil
Если ответил, копните глубже
UIView.animate не создаёт цикл?sink в Combine приводит к утечке?Объясни решение задачи «минимальное число монет для суммы» и его сложность. Почему тут не подходит жадность?
Что хотим услышать
- Показывает контрпример для жадности
- Формулирует состояние: dp[s] минимум монет для суммы s
- Переход: dp[s] = min(dp[s - c] + 1) по монетам
- База dp[0] = 0, остальные Infinity, недостижимо → -1
- O(S · k) времени, O(S) памяти
Если ответил, копните глубже
Чем отличаются сессии на куках и JWT? Что бы ты выбрал для обычного веб-приложения?
Что хотим услышать
- Сессия: id в куке, состояние на сервере (Redis/БД), отзыв мгновенный
- JWT: состояние в самом токене, проверка подписью без базы, сложно отозвать
- Для JWT нужна пара короткий access + отзываемый refresh
- Хранение: HttpOnly кука защищает от XSS, но нужна защита от CSRF (SameSite)
- Выбор по контексту: одно веб-приложение проще на сессиях, много сервисов и мобильные клиенты удобнее на токенах
Если ответил, копните глубже
Расскажите, как устроены слои в вашем мобильном приложении и зачем.
Что хотим услышать
- Presentation, domain, data и направление зависимостей внутрь
- Интерфейсы репозиториев в домене, реализации в data, связывание через DI
- Маппинг DTO и entity в доменные модели на границе
- Ошибки переводятся в доменные на границе data
- Use case только там, где есть логика или переиспользование
- Слои внутри фич, а не глобальные папки
Если ответил, копните глубже
Как бы ты построил CI/CD для веб-приложения с нуля?
Что хотим услышать
- На каждый PR: npm ci, линтер, типы, unit-тесты, сборка
- Быстрые проверки первыми, независимые джобы параллельно, кеш зависимостей
- Защита ветки main: мерж только с зелёным CI и ревью
- Сборка один раз, артефакт (образ) с версией продвигается по стендам
- Деплой на стенд автоматически, на прод с подтверждением или автоматически при хорошем покрытии
- План отката и миграции, совместимые с предыдущей версией
Если ответил, копните глубже
Почему вы ищете новую работу?
Что хотим услышать
- Причина через цель, а не через бегство
- Ни слова негатива о текущем работодателе
- Показано, что на текущем месте был рост и результаты
- Связка с этой вакансией
- Коротко: до минуты
Если ответил, копните глубже
Расскажите, как замыкания захватывают переменные и какие проблемы это создаёт.
Что хотим услышать
- По умолчанию захват переменной (ссылка на бокс), видно последнее значение
- Список захвата
[x]копирует значение в момент создания - Захват
selfкласса сильный: риск цикла ссылок в escaping-замыкании [weak self]иguard let self,[unowned self]только при гарантии жизни- Non-escaping по умолчанию, escaping при сохранении или асинхронности
- Замыкания ссылочные: копия делит захваченное состояние
Если ответил, копните глубже
self. в escaping-замыкании?[weak self] в UIView.animate?Объясни, как работает BFS, почему он находит кратчайший путь в графе без весов и какая у него сложность.
Что хотим услышать
- Очередь и пометка посещённых при добавлении
- Вершины обрабатываются в порядке неубывания расстояния
- Первое посещение вершины даёт кратчайшее расстояние
- O(V + E) времени и O(V) памяти
- Знает, что при весах нужен Дейкстра
Если ответил, копните глубже
Чем отличаются HTTP/1.1, HTTP/2 и HTTP/3? Какие проблемы решала каждая версия?
Что хотим услышать
- Семантика (методы, статусы, заголовки) одна, меняется транспорт
- HTTP/1.1: запросы по очереди в соединении, браузер держит около 6 соединений
- HTTP/2: бинарные фреймы, мультиплексирование, HPACK, одно соединение
- HTTP/2 упирается в head-of-line blocking TCP при потерях
- HTTP/3: QUIC поверх UDP, независимые потоки, TLS встроен, быстрее рукопожатие, миграция соединения
Если ответил, копните глубже
Расскажите, как вы строите CI/CD для мобильного приложения.
Что хотим услышать
- PR-пайплайн: сборка, линтеры, юнит-тесты, проверка размера
- Релизный пайплайн: версия, подпись, загрузка символов, публикация в тестовые треки
- Секреты и ключи подписи вне репозитория
- Ускорение: кеш сборки, разделение по модулям, параллельные задачи
- Раскатка: поэтапно, метрики, флаги, хотфиксы
- Ночные сборки: UI-тесты, полный регресс
Если ответил, копните глубже
Как бы ты написал Dockerfile для Node.js-сервиса в прод? Что в нём важно?
Что хотим услышать
- Конкретный базовый образ (node:22-alpine или slim), не latest
- Порядок слоёв: сначала манифесты и npm ci, потом исходники
- Multi-stage: сборка отдельно, в финале только dist и прод-зависимости
- .dockerignore: node_modules, .git, .env
- USER node, не root
- Exec-форма CMD, healthcheck, секреты не в образе
Если ответил, копните глубже
Почему вы считаете себя middle-разработчиком?
Что хотим услышать
- Показал самостоятельность: вёл задачу сам от требований до прода
- Привёл пример фичи, которую довёл целиком
- Упомянул работу с неясными требованиями
- Есть результат с цифрой
- Не завысил и не принизил себя
Если ответил, копните глубже
Senior: 12 вопросов
Глубина и опыт: границы подходов, решения в продакшене.
Чем ARC в Swift отличается от сборщика мусора в Java/Kotlin, какие плюсы и минусы?
Что хотим услышать
- ARC: подсчёт ссылок вставляется компилятором, освобождение детерминированное
- Нет пауз сборщика и фоновых потоков,
deinitвызывается сразу - Минус: циклы не собираются, ответственность на разработчике (
weak/unowned) - Минус: атомарные retain/release стоят времени, компилятор их частично убирает
- GC: собирает циклы, но паузы и выше пиковое потребление памяти
Если ответил, копните глубже
Как бы ты сделал надёжный клиент WebSocket для чата, который переживает обрывы сети?
Что хотим услышать
- Реконнект с экспоненциальной задержкой и джиттером, сброс задержки после успеха
- Heartbeat: ping/pong с таймаутом, при пропуске закрыть и переподключиться
- Нумерация сообщений: после реконнекта клиент сообщает последний id, сервер досылает пропущенное
- Очередь исходящих сообщений с клиентскими id, идемпотентность на сервере против дублей
- Реакция на
online/offlineи видимость вкладки, повторная авторизация при истёкшем токене
Если ответил, копните глубже
Как вы решаете, какие ответы API кешировать, где и на сколько?
Что хотим услышать
- Классификация данных по свежести и цене устаревания
- Где хранить: память, диск, база, HTTP-кеш
- Стратегии чтения: cache first, network first, SWR
- Инвалидация: TTL, версии, события (push, действия пользователя)
- Персональные данные в скоупе сессии, очистка при выходе
- Метрики: hit rate, трафик, время до контента
Если ответил, копните глубже
Ты приходишь в проект без тестов. Как выстроишь стратегию тестирования?
Что хотим услышать
- начать с самого рискованного и ценного для бизнеса: оплата, вход, ключевые сценарии
- несколько e2e smoke-тестов на критичные пути
- unit-тесты на чистую логику: расчёты, форматирование, утилиты
- интеграционные тесты компонентов и API на новых и изменяемых местах
- тесты в CI как обязательная проверка PR
- регрессионный тест на каждый найденный баг, борьба с флаки
Если ответил, копните глубже
Вы претендуете на senior. Расскажите о себе.
Что хотим услышать
- Назван масштаб: команда, нагрузка, пользователи или деньги
- Есть решения, которые повлияли дальше своего кода
- Есть метрики результата
- Упомянуто влияние на команду: менторинг, процессы, ревью
- Уложился в 2 минуты, не утонул в деталях
Если ответил, копните глубже
Как вы реализуете принудительное и мягкое обновление приложения?
Что хотим услышать
- Сервер или удалённый конфиг отдаёт минимальную и рекомендуемую версии
- Клиент сравнивает версии покомпонентно, а не как строки
- Ниже минимальной: блокирующий экран со ссылкой в App Store
- Ниже рекомендуемой: ненавязчивое предложение обновиться
- API держит обратную совместимость, принудительное обновление крайняя мера
- Учесть офлайн и задержку ревью: минимальную версию поднимать после раскатки
Если ответил, копните глубже
Первая загрузка сайта занимает 4 секунды у пользователей из регионов. Как бы ты искал, где теряется время, и что делал?
Что хотим услышать
- Измерить: Navigation Timing и RUM по этапам (DNS, connect, TLS, TTFB, загрузка, рендер), Lighthouse и WebPageTest
- Сеть: CDN ближе к пользователю, HTTP/2 или HTTP/3, preconnect к сторонним доменам
- Сервер: медленный TTFB → кеширование, отдача статики с CDN, 103 Early Hints
- Ресурсы: Brotli, меньше JS, code splitting, оптимизированные картинки с размерами
- Рендер: критический CSS, defer для скриптов, без блокирующих сторонних скриптов
Если ответил, копните глубже
Новый проект: MVP приложения за два месяца. Будете ли вы делать полноценную Clean Architecture?
Что хотим услышать
- Цена слоёв: шаблонный код, мапперы, скорость команды
- Минимум, который нужен всегда: границы на краях (сеть и база за интерфейсами), DI, тестируемые view model
- Domain-слой добавляется, когда появляется бизнес-логика
- Структура по фичам упрощает будущее разделение
- Решение фиксируется в ADR и пересматривается
Если ответил, копните глубже
Чем, по-вашему, резюме senior должно отличаться от резюме middle?
Что хотим услышать
- Акцент на масштаб и влияние, а не на список фич
- Метрики бизнес-эффекта
- Лидерство: менторинг, процессы, архитектурные решения
- Компактность: старый опыт свёрнут
- Понимание, что резюме под роль, а не под всё сразу
Если ответил, копните глубже
Расскажите, как работают акторы и какие у них подводные камни.
Что хотим услышать
- Актор сериализует доступ к своему состоянию, снаружи
await - Реентерабельность: на
awaitвнутри метода выполняются другие вызовы - Инварианты нельзя проверять до
awaitи использовать после - Слияние одинаковых запросов через хранение
Taskв акторе nonisolatedдля методов без доступа к состоянию,@MainActorдля UI- Глобальные акторы и переходы между доменами имеют цену (hop)
Если ответил, копните глубже
isolated параметр?Как бы ты включил HTTP/3 на проде и как убедился бы, что он даёт пользу?
Что хотим услышать
- Нужна поддержка на edge: CDN или nginx с QUIC, открытый UDP 443
- Сервер объявляет Alt-Svc, опционально DNS-запись HTTPS
- HTTP/2 остаётся как запасной путь для сетей без UDP
- Проверка: протокол в DevTools (h3), доля h3 в логах
- Польза в RUM-метриках (TTFB, LCP) по мобильным и сетям с потерями
Если ответил, копните глубже
Как вы организуете совместимость бэкенда и множества версий мобильного приложения?
Что хотим услышать
- Мобильные версии живут месяцами, статистика версий в аналитике
- Аддитивные изменения API, версионирование эндпоинтов
- Клиент устойчив к неизвестным полям и значениям enum
- Флаги и удалённый конфиг для поведения
- Минимальная поддерживаемая версия и мягкое и жёсткое обновление
- Контрактные тесты между клиентом и сервером
Если ответил, копните глубже
Задача для live coding
Задача на Swift: самая длинная подстрока без повторов
Найдите длину самой длинной подстроки без повторяющихся символов.
Ввод: строка из строчных латинских букв длиной от 1 до 5·10⁴.
Пример
abcabcbb
3
Скользящее окно и последняя позиция символа.
Эталон, тесты и таймер открываются интервьюеру в живом моке
Рубрика оценки: 1-4 балла
Те же критерии процесса, что в живом моке Техпрогона. Ставьте балл по каждому пункту, сумма показывает картину лучше, чем «понравился или нет».
Уточнил условие
Ограничения, формат входа, что вернуть при пустом вводе
Привёл примеры до кода
Обычный случай и хотя бы один краевой
Проговорил алгоритм словами
До того как писать код
Назвал сложность
По времени и по памяти
Написал рабочий код
Тесты прошли
Сам проверил краевые случаи
Прогнал в голове пустой ввод, один элемент, дубликаты
Нашёл и исправил ошибку сам
Или ошибок не было с первого раза
Мок-собес без регистрации для интервьюера
Хотите проверить кандидата на задаче с эталоном и рубрикой? Так работает живой мок в Техпрогоне.
Кандидат готовится в Техпрогоне и на задаче открывает ступень «Живой мок».
Он присылает вам ссылку. Вы открываете её без регистрации.
У вас условие, эталон, рубрика, уточняющие вопросы и таймер.
Вы ставите оценки и вердикт, кандидат сразу видит результат.
Для интервьюера бесплатно. Ссылку создаёт кандидат на тарифе Рывок
Наборы для других ролей
Готовитесь к собесу сами? Подготовка к собеседованию: iOS-разработчик