Подготовка к собеседованию — iOS-разработчик
Колода из 153+ карточек с вопросами для собеседования по направлению «iOS-разработчик» — по темам и уровню сложности, с возвратом ровно перед тем, как вы забудете. Посмотрите несколько карточек ниже, затем войдите, чтобы учить всё направление по расписанию в стиле Anki (SM-2).
Бесплатно · вход через GitHub · ваш прогресс остаётся с вами.
Что внутри
Все темы направления, сгруппированные так, как вы будете их учить.
Swift и система типов
12 карточекПамять и ARC
9 карточекМногопоточность: GCD и Swift Concurrency
11 карточекUIKit и вёрстка
10 карточекSwiftUI
8 карточекАрхитектура iOS-приложений
8 карточекСеть и хранение данных
9 карточекПроизводительность и инструменты
8 карточекОсновы CS
43 карточкиПоведенческое интервью
35 карточекПримеры вопросов
Несколько карточек из колоды — откройте ответ, затем войдите, чтобы учить весь набор по расписанию.
В чём реальные различия между struct и class в Swift?
В чём реальные различия между struct и class в Swift?
Короткий ответ: struct — значимый тип: при присваивании и передаче в функцию значение копируется. class — ссылочный: переменные разделяют один экземпляр. Наследование, deinit и идентичность (===) есть только у классов; мутация структуры требует var и mutating-методов.
Подробно:
struct |
class |
|
|---|---|---|
| Семантика | копия значения | общая ссылка |
| Наследование | ✗ (только протоколы) | ✓ |
deinit / === |
✗ | ✓ |
| Мутация | mutating + var |
всегда, даже через let |
| ARC | нет retain/release (если нет ссылочных полей) | есть |
| Инициализатор | memberwise бесплатно | пишешь сам |
- По умолчанию — struct — предсказуемое копирование, нет гонок на общем состоянии, дешевле для ARC.
- Класс — когда нужна общая идентичность (кэш, сервис), наследование от NSObject-мира или
deinitдля освобождения ресурса.
⚠️ Частая ошибка: «структуры всегда живут на стеке». Нет: структура — поле класса, захвачена escaping-замыканием или упакована в экзистенциал с большим payload — живёт в куче. Value type определяет семантику копирования, а не место в памяти.
Как работает ARC и чем он отличается от сборщика мусора?
Как работает ARC и чем он отличается от сборщика мусора?
Короткий ответ: ARC — автоматический подсчёт ссылок: компилятор ещё на этапе компиляции вставляет вызовы retain/release вокруг работы с сильными ссылками. Объект умирает ровно в момент, когда счётчик ссылок падает до нуля — детерминированно и без пауз. Цена: циклы ссылок ARC собрать не может.
Подробно:
| ARC | Трассирующий GC | |
|---|---|---|
| Кто решает | компилятор: вставка retain/release | рантайм: обход графа объектов |
| Момент освобождения | детерминированный: счётчик = 0 | недетерминированный, при сборке |
| Паузы | нет | stop-the-world / инкрементальные |
| Циклы | не собирает — нужны weak/unowned | собирает автоматически |
| Накладные расходы | атомарные инкременты счётчика | память под кучу + CPU на трассировку |
- Компилятор, а не рантайм — retain вставляется при появлении новой сильной ссылки, release — при выходе из области видимости; оптимизатор выкидывает парные лишние вызовы.
- Детерминированный deinit — ресурс освобождается сразу, поэтому deinit пригоден для закрытия файлов, инвалидации таймеров, отписок.
- Плата — ретейн-циклы остаются ответственностью программиста.
⚠️ Частая ошибка: называть ARC «сборщиком мусора, только быстрее». ARC не сканирует память в рантайме — вся работа расставлена компилятором заранее, поэтому и пауз нет, и циклы сами не находятся.
Чем serial очередь отличается от concurrent, что такое main и global — и почему очередь это не поток?
Чем serial очередь отличается от concurrent, что такое main и global — и почему очередь это не поток?
Короткий ответ: Очередь — абстракция «список задач», а не поток: GCD мультиплексирует очереди по общему пулу потоков. Serial выполняет задачи строго по одной в порядке FIFO, concurrent запускает несколько параллельно. Main — единственная очередь с контрактом «выполняюсь на мейн-треде»; global — системные concurrent очереди, по одной на класс QoS.
Подробно:
| Очередь | Тип | Особенность |
|---|---|---|
DispatchQueue.main |
serial | привязана к мейн-треду; весь UI |
DispatchQueue.global(qos:) |
concurrent | системные, общие на приложение |
DispatchQueue(label:) |
serial по умолчанию | своя; attributes: .concurrent — параллельная |
| QoS | Для чего |
|---|---|
.userInteractive |
анимации, реакция на жест — «прямо сейчас» |
.userInitiated |
пользователь ждёт результат (открытие экрана) |
.utility |
долгая работа с прогрессом (загрузка файла) |
.background |
невидимая работа: синк, индексация |
- Очередь ≠ поток — serial очередь не владеет потоком: её задачи могут выполняться на разных потоках пула, но никогда одновременно.
- QoS решает планирование — системе QoS говорит, сколько CPU и энергии дать:
.userInteractive— вне очереди,.backgroundможет подождать.
⚠️ Частая ошибка: «создал очередь — создал поток». Нет: тысячи очередей обслуживаются десятком потоков пула. А вот заблокировать много потоков через sync-ожидания — путь к thread explosion.
Жизненный цикл UIViewController: в каком порядке вызываются методы и что где делать?
Жизненный цикл UIViewController: в каком порядке вызываются методы и что где делать?
Короткий ответ: loadView создаёт вью → viewDidLoad — одноразовая настройка (геометрии ещё нет!) → viewWillAppear — обновление перед каждым показом → viewWillLayoutSubviews/viewDidLayoutSubviews — единственные места, где фреймы валидны → viewDidAppear — анимации и тяжёлые старты → viewWillDisappear/viewDidDisappear.
Подробно:
loadView ─► viewDidLoad ─► viewWillAppear ─► viewWillLayoutSubviews
(создать (один раз) (каждый показ) │ layout pass
view) ▼
viewDidDisappear ◄─ viewWillDisappear ◄─ viewDidAppear ◄─ viewDidLayoutSubviews
(на экране) (фреймы валидны!)
viewDidLoad— один раз за жизнь вью-контроллера: добавить сабвью, констрейнты, подписки. Размеров вью ещё нет.viewWillAppear— каждый показ: обновить данные, состояние баров.viewDidLayoutSubviews— bounds актуальны: скругления, путиCAShapeLayer, зависящая от размеров вёрстка. Вызывается многократно — без тяжёлой работы.viewDidAppear— вью на экране: запуск анимаций, дорогие операции, аналитика.viewWillDisappear/viewDidDisappear— остановить таймеры, сохранить состояние.
⚠️ Частая ошибка: читать view.bounds в viewDidLoad — там либо размер из сториборда, либо нули, но не реальная геометрия устройства. Всё, что зависит от размеров, живёт в viewDidLayoutSubviews.
Почему View в SwiftUI — структуры, и почему их постоянное пересоздание не дорого?
Почему View в SwiftUI — структуры, и почему их постоянное пересоздание не дорого?
Короткий ответ: View — не вью в смысле UIKit, а лёгкое значение-описание: чертёж того, что показать. Структуры дёшево создавать и выбрасывать, поэтому SwiftUI свободно пересоздаёт их при каждом пересчёте body. Долгоживущая часть — render tree (attribute graph) — живёт за кулисами; именно там хранятся состояние и идентичность.
Подробно:
- Чертёж, а не экземпляр — UIView — тяжёлый объект с жизненным циклом и слоем; View-структура — пара полей и body, без ресурсов.
- Состояние снаружи — @State хранится фреймворком и привязан к идентичности вью в дереве, а не к структуре: структура умерла, значение осталось.
- Diffing — SwiftUI сравнивает новое описание со старым и минимально мутирует персистентное дерево; в пиксели уходит только разница.
body → View-значения (дёшево, пересоздаются каждый раз)
│ diff
▼
attribute graph / render tree (живёт долго:
@State, идентичность, анимации)
⚠️ Частая ошибка: приравнять «пересоздание структур» к «перерисовке UI». Создание описаний — копейки; дорогим бывает рендер, и он происходит только там, где diff нашёл изменение.
Почему Apple-овский MVC превращается в Massive View Controller и как разгрузить вью-контроллер, не меняя архитектуру?
Почему Apple-овский MVC превращается в Massive View Controller и как разгрузить вью-контроллер, не меняя архитектуру?
Короткий ответ: Потому что в UIKit вью-контроллер по умолчанию — точка сборки всего: жизненный цикл вью, лейаут, data source таблицы, навигация и сетевые вызовы. Разгружается он выносом обязанностей в отдельные объекты — менять архитектуру для этого не обязательно.
Подробно:
- Диагноз — MVC у Apple не плох сам по себе; проблема в том, что «C» удобно принимает любой код, и без дисциплины вью-контроллер растёт до тысяч строк.
- Что выносить:
| Обязанность | Куда выносится |
|---|---|
UITableViewDataSource / delegate |
отдельный объект-датасорс |
| Кусок экрана со своей логикой | child view controller |
| Сеть, кэш, аналитика | простые сервисные объекты |
| Конфигурация сабвью | сами вью (configure(with:)) |
- Итог — вью-контроллер остаётся дирижёром: связывает сервисы, вью и навигацию, но не делает всю работу сам.
⚠️ Частая ошибка: отвечать «MVC — плохая архитектура, поэтому все ушли в MVVM». Плоха недисциплинированная реализация: без выноса обязанностей тот же перегруз повторится и с ViewModel.
Готовы закрепить навсегда?
Первая сессия — меньше минуты. Ваше будущее «я» на собеседовании скажет спасибо.
Вопросы об этом направлении
Как готовиться к собеседованию на «iOS-разработчик»?
Учите концепции, которые придётся объяснять, а не только те, что умеете кодить. Направление «iOS-разработчик» в RecallDeck даёт 153+ отобранных вопросов и возвращает каждый по расписанию в стиле Anki (SM-2) ровно перед тем, как вы забудете — чтобы на собеседовании ответы были под рукой.
Какие темы охватывает направление «iOS-разработчик»?
Направление «iOS-разработчик» разбито на ключевые области, которые реально проверяют на таких собеседованиях, — по темам и уровню сложности (Concept, Junior, Middle, Senior). Полный план и примеры вопросов можно посмотреть выше до входа.
Помогает ли интервальное повторение в подготовке к «iOS-разработчик»?
Да. Активно вспоминать ответ и честно себя оценивать — куда прочнее для памяти, чем перечитывать заметки. RecallDeck планирует каждую карту «iOS-разработчик» так, чтобы она вернулась перед моментом забывания: ежедневных повторений становится меньше, а знания держатся.
Направление «iOS-разработчик» бесплатное?
Да — направление «iOS-разработчик» и полный планировщик SM-2 бесплатны, с 20 новыми картами в день. Войдите через GitHub, и прогресс синхронизируется с аккаунтом. RecallDeck Pro ($5/мес или $29/год) поднимает дневной лимит и добавляет блиц-режим.