Направление

Подготовка к собеседованию — iOS-разработчик

Колода из 153+ карточек с вопросами для собеседования по направлению «iOS-разработчик» — по темам и уровню сложности, с повторениями по вашим оценкам. Посмотрите несколько карточек ниже, затем выберите доступ, чтобы учить всё направление по расписанию в стиле Anki (SM-2).

153 карточки10 тем
Посмотреть цены и начать

Новым подписчикам месяца или года может быть доступно 7 дней бесплатно. Условия и сумму подтвердит страница оплаты.

С чего начать

Нужны основы Swift и опыт создания небольшого iOS-приложения. В общих алгоритмах есть примеры на Python; концепции применимы и в Swift, но их реализацию стоит потренировать отдельно.

Первый проход: Swift и система типов → Память и ARC. Начните с базовых вопросов в этих модулях, затем продолжайте по плану. К сложным и senior-вопросам возвращайтесь по требованиям вакансии; все карточки доступны с самого начала.

Общие темы могут входить в несколько направлений и сохраняют одну историю повторений. План ниже отмечает общие основы и профильные модули; выбирайте глубину под свою вакансию.

Что внутри

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

Swift и система типов

12 карточек

Профильный модуль

Swift и типы

Память и ARC

9 карточек

Профильный модуль

Память и ARC

Многопоточность: GCD и Swift Concurrency

11 карточек

Профильный модуль

GCD и Swift Concurrency

UIKit и вёрстка

10 карточек

Профильный модуль

UIKit и вёрстка

SwiftUI

8 карточек

Профильный модуль

SwiftUI

Архитектура iOS-приложений

8 карточек

Профильный модуль

Архитектура

Сеть и хранение данных

9 карточек

Профильный модуль

Сеть и хранение

Производительность и инструменты

8 карточек

Профильный модуль

Производительность

Основы CS

43 карточки

Общие основы

Структуры данных и алгоритмы

Поведенческое интервью

35 карточек

Общие основы

Поведенческое интервью

Примеры вопросов

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

В чём реальные различия между struct и class в Swift?

Короткий ответ: struct — значимый тип, class — ссылочный тип с идентичностью. Обычная копируемая структура имеет семантику копирования; присваивание ссылки на класс разделяет экземпляр. Наследование и === относятся к классам. С Swift 5.9 существуют некопируемые структуры ~Copyable: они могут иметь deinit, но не допускают обычного копирования.

Подробно:

struct class
Семантика значение; обычно Copyable общая ссылка
Наследование нет, но есть протоколы есть
Идентичность === нет есть
deinit у некопируемых структур есть
Мутация для изменения хранимых полей нужны var и mutating-методы свойства var можно менять и через ссылку let
ARC может применяться к ссылочным полям управляет временем жизни экземпляра
Инициализатор memberwise при выполнении условий синтеза автоматический default/inherited — лишь при определённых условиях
  1. Структура удобна для независимых значений. Копирование может быть оптимизировано, например через copy-on-write; ссылочные поля всё равно могут разделять изменяемое состояние.
  2. Класс нужен, когда важна общая идентичность или наследование. Безопасность потоков не следует автоматически ни из struct, ни из class.
  3. Некопируемый ресурс можно моделировать struct Resource: ~Copyable { deinit {} }: владение передают без копирования.

⚠️ Частая ошибка: «структуры всегда живут на стеке». Семантика значения не определяет размещение в памяти: структура может находиться внутри объекта в куче или быть упакована в экзистенциал.

Как работает ARC и чем он отличается от сборщика мусора?

Короткий ответ: ARC автоматически управляет сильными ссылками: компилятор вставляет и оптимизирует retain/release, а эти операции выполняются во время работы программы. Когда исчезает последняя сильная ссылка, объект может быть уничтожен. ARC не ищет недостижимые циклы, поэтому сильные циклы нужно разрывать явно.

Подробно:

ARC Трассирующий GC
Механизм подсчёт сильных ссылок, подготовленный компилятором обход достижимого графа во время сборки
Освобождение при последнем release; его точка зависит от времени жизни и оптимизации по политике сборщика после установления недостижимости
Задержки retain/release и синхронная цепочка deinit могут стоить времени зависят от реализации: паузы, инкрементальная или конкурентная работа
Циклы недостижимый сильный цикл сам не собирается недостижимые циклы могут быть собраны
  1. Время жизни — последняя строка области видимости не обязательно совпадает с последним release. Оптимизатор может менять время жизни в разрешённых языком пределах; при необходимости используют withExtendedLifetime.
  2. Ресурсы — deinit полезен для финальной очистки, но для обязательного своевременного close, отмены или отписки лучше явная операция и, где подходит, defer. Retain cycle может вообще не дать deinit выполниться.
  3. Слабые ссылки — weak не удерживает объект и обнуляется; unowned требует доказательства, что объект ещё жив при обращении. Выбор следует из модели владения.

⚠️ Частая ошибка: «ARC работает только при компиляции и не имеет пауз». Во время выполнения остаются расходы на подсчёт ссылок и освобождение, а дорогой deinit может задержать поток.

Чем 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 невидимая работа: синк, индексация
  1. Очередь ≠ поток — serial очередь не владеет потоком: её задачи могут выполняться на разных потоках пула, но никогда одновременно.
  2. QoS решает планирование — системе QoS говорит, сколько CPU и энергии дать: .userInteractive — вне очереди, .background может подождать.

⚠️ Частая ошибка: «создал очередь — создал поток». Нет: тысячи очередей обслуживаются десятком потоков пула. А вот заблокировать много потоков через sync-ожидания — путь к thread explosion.

Жизненный цикл UIViewController: в каком порядке вызываются методы и что где делать?

Короткий ответ: loadView создаёт вью → viewDidLoad — одноразовая настройка (геометрии ещё нет!) → viewWillAppear — обновление перед каждым показом → viewWillLayoutSubviews/viewDidLayoutSubviews — единственные места, где фреймы валидны → viewDidAppear — анимации и тяжёлые старты → viewWillDisappear/viewDidDisappear.

Подробно:

loadView ─► viewDidLoad ─► viewWillAppear ─► viewWillLayoutSubviews
 (создать    (один раз)     (каждый показ)          │ layout pass
  view)                                             ▼
viewDidDisappear ◄─ viewWillDisappear ◄─ viewDidAppear ◄─ viewDidLayoutSubviews
                                          (на экране)      (фреймы валидны!)
  1. viewDidLoad — один раз за жизнь вью-контроллера: добавить сабвью, констрейнты, подписки. Размеров вью ещё нет.
  2. viewWillAppear — каждый показ: обновить данные, состояние баров.
  3. viewDidLayoutSubviews — bounds актуальны: скругления, пути CAShapeLayer, зависящая от размеров вёрстка. Вызывается многократно — без тяжёлой работы.
  4. viewDidAppear — вью на экране: запуск анимаций, дорогие операции, аналитика.
  5. viewWillDisappear/viewDidDisappear — остановить таймеры, сохранить состояние.

⚠️ Частая ошибка: читать view.bounds в viewDidLoad — там либо размер из сториборда, либо нули, но не реальная геометрия устройства. Всё, что зависит от размеров, живёт в viewDidLayoutSubviews.

Почему View в SwiftUI — структуры, и почему их постоянное пересоздание не дорого?

Короткий ответ: View — не вью в смысле UIKit, а лёгкое значение-описание: чертёж того, что показать. Структуры дёшево создавать и выбрасывать, поэтому SwiftUI свободно пересоздаёт их при каждом пересчёте body. Долгоживущая часть — render tree (attribute graph) — живёт за кулисами; именно там хранятся состояние и идентичность.

Подробно:

  1. Чертёж, а не экземпляр — UIView — тяжёлый объект с жизненным циклом и слоем; View-структура — пара полей и body, без ресурсов.
  2. Состояние снаружи — @State хранится фреймворком и привязан к идентичности вью в дереве, а не к структуре: структура умерла, значение осталось.
  3. Diffing — SwiftUI сравнивает новое описание со старым и минимально мутирует персистентное дерево; в пиксели уходит только разница.
body → View-значения (дёшево, пересоздаются каждый раз)
            │ diff
            ▼
attribute graph / render tree (живёт долго:
@State, идентичность, анимации)

⚠️ Частая ошибка: приравнять «пересоздание структур» к «перерисовке UI». Создание описаний — копейки; дорогим бывает рендер, и он происходит только там, где diff нашёл изменение.

Почему Apple-овский MVC превращается в Massive View Controller и как разгрузить вью-контроллер, не меняя архитектуру?

Короткий ответ: Потому что в UIKit вью-контроллер по умолчанию — точка сборки всего: жизненный цикл вью, лейаут, data source таблицы, навигация и сетевые вызовы. Разгружается он выносом обязанностей в отдельные объекты — менять архитектуру для этого не обязательно.

Подробно:

  1. Диагноз — MVC у Apple не плох сам по себе; проблема в том, что «C» удобно принимает любой код, и без дисциплины вью-контроллер растёт до тысяч строк.
  2. Что выносить:
Обязанность Куда выносится
UITableViewDataSource / delegate отдельный объект-датасорс
Кусок экрана со своей логикой child view controller
Сеть, кэш, аналитика простые сервисные объекты
Конфигурация сабвью сами вью (configure(with:))
  1. Итог — вью-контроллер остаётся дирижёром: связывает сервисы, вью и навигацию, но не делает всю работу сам.

⚠️ Частая ошибка: отвечать «MVC — плохая архитектура, поэтому все ушли в MVVM». Плоха недисциплинированная реализация: без выноса обязанностей тот же перегруз повторится и с ViewModel.

Готовы лучше запоминать?

Посмотрите пример, выберите направление и настройте регулярную практику под свою подготовку.

Вопросы об этом направлении

Как готовиться к собеседованию на «iOS-разработчик»?

Учите концепции, которые придётся объяснять, а не только те, что умеете кодить. Направление «iOS-разработчик» в RecallDeck даёт 153+ отобранных вопросов и возвращает каждый по расписанию в стиле Anki (SM-2), основанному на ваших оценках — чтобы тренировать вспоминание и объяснение. Дополняйте повторения кодингом и пробными собеседованиями.

Какие темы охватывает направление «iOS-разработчик»?

Направление «iOS-разработчик» разбито на ключевые области, которые реально проверяют на таких собеседованиях, — по темам и уровню сложности (Concept, Junior, Middle, Senior). Полный план и примеры вопросов можно посмотреть выше до входа.

Помогает ли интервальное повторение в подготовке к «iOS-разработчик»?

Да. Активное вспоминание и честная самооценка помогают закреплять знания. RecallDeck назначает повторения карт по направлению «iOS-разработчик» на основе ваших оценок: знакомые карты возвращаются реже, а сложные получают больше практики.

Можно попробовать направление «iOS-разработчик» до оплаты?

Новым подписчикам месячного или годового тарифа может быть доступен пробный период семь дней со всем направлением «iOS-разработчик» и всеми функциями. Право на него и сумму подтвердит страница оплаты; при повторной подписке списание может быть сразу. Отмените подписку онлайн до конца пробного периода, чтобы избежать первого списания. У вечного доступа пробного периода нет.

Другие направления