AI
prepair.app
Пройти интервью →
EnglishУкраїнськаРусский
🍏

Senior iOS (Swift)Вопросы на собеседовании iOS разработчика

Senior · 5+ лет опыта

Собеседование iOS-разработчика проверяет систему типов Swift, понимание ARC и умение рассуждать о состоянии интерфейса — плюс обязательно найдётся вопрос, где retain cycle прячется на виду. Ниже — вопросы, которые задают чаще всего, каждый с эталонным ответом. Senior: архитектуру, трейд-оффы, менторство и принятие решений.

Темы для подготовки

Swift и опционалы
ARC и управление памятью
SwiftUI и UIKit
Конкурентность: async/await, Combine, GCD
Архитектура и состояние
Хранение данных и сеть

9 вопросов уровня Senior с ответами

1

Когда использовать weak, а когда unowned?

Ответ

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

2

В чём разница между @State, @Binding, @StateObject и @ObservedObject?

Ответ

@State — локальное состояние значимого типа, которым владеет вью; SwiftUI хранит его вне структуры, поэтому оно переживает перерисовки. @Binding — ссылка на чужое состояние с правом записи, именно так дочерний вью меняет значение родителя. @StateObject создаёт и владеет ссылочным observable-объектом и инициализируется ровно один раз. @ObservedObject наблюдает за объектом, которым владеет кто-то другой — если поставить его там, где нужен @StateObject, объект будет пересоздаваться на каждой перерисовке и молча терять состояние.

3

Как SwiftUI решает, что вью нужно перерисовать?

Ответ

Вью — это лёгкая структура, описывающая интерфейс; SwiftUI пересобирает её body всякий раз, когда меняется прочитанная ею зависимость, затем сравнивает результат с предыдущим деревом и применяет только различия. Зависимости — это те property wrapper-ы, которые вью реально читает, плюс Environment. Проблемы производительности почти всегда идут от состояния, поднятого слишком высоко по дереву: не связанное изменение инвалидирует большое поддерево.

4

Что меняет async/await по сравнению с completion-хендлерами и GCD?

Ответ

async/await позволяет читать асинхронный код сверху вниз, поэтому обработка ошибок идёт обычным try/catch, нет «пирамиды вложенности» и забытых веток завершения. Компилятор следит, чтобы await вызывался в async-контексте, а структурная конкурентность привязывает жизнь дочерних задач к родительской, так что отмена распространяется автоматически. GCD остаётся актуальным для легаси и тонкого управления очередями, но новый код стоит писать на async/await, оставив Combine для настоящих потоков значений во времени.

5

Что такое escaping-замыкание и зачем нужно это ключевое слово?

Ответ

Замыкание считается escaping, если оно сохраняется и вызывается уже после возврата из функции — например, completion-хендлер сетевого запроса. Swift требует пометки @escaping, потому что не-escaping замыкание можно агрессивнее оптимизировать и оно не может случайно сильно захватить self. Эта пометка ещё и сигнал подумать о семантике захвата: именно в escaping-замыканиях рождаются retain cycle.

6

Разберите жизненный цикл UIViewController. Где размещать код вёрстки?

Ответ

viewDidLoad выполняется один раз после загрузки иерархии вью и предназначен для разовой настройки. viewWillAppear и viewDidAppear вызываются при каждом показе — туда идёт то, что должно повторяться: обновление данных, запуск анимации. Вёрстка, зависящая от финальных размеров, живёт в viewDidLayoutSubviews, потому что в viewDidLoad границы ещё не окончательные — вычисление фреймов там очень частый баг, который проявляется только на другом размере экрана.

7

Как выбрать между Core Data, SwiftData и просто файлами?

Ответ

Core Data оправдывает свою сложность, когда данные реляционные и нужны запросы, ленивая подгрузка и отслеживание изменений на большом графе объектов. SwiftData — современная нативная для Swift обёртка над тем же стеком, дефолт для новых приложений на свежих версиях ОС. Для десятка настроек берут UserDefaults, а для кеша декодированных моделей обычные Codable-файлы или лёгкое key-value хранилище понятнее, чем полноценный persistent container.

8

Как диагностировать медленный запуск или утечку памяти?

Ответ

Для времени запуска берут шаблон App Launch в Instruments и смотрят, что выполняется до первого кадра; обычные виновники — синхронная работа с диском или сетью в didFinishLaunching и тяжёлый граф зависимостей, собираемый заранее. Для утечек Memory Graph Debugger показывает объекты, которые должны были освободиться, и того, кто на них ещё ссылается, — это напрямую вскрывает retain cycle. Инструмент Leaks ловит классические утечки, но граф удобнее для циклов, потому что он называет удерживающую ссылку.

9

Что вы тестируете в iOS, а что сознательно не тестируете?

Ответ

Юнит-тестами покрывают бизнес-логику, вью-модели и чистые преобразования — всё, у чего есть вход и выход и нет зависимости от UIKit. XCUITest берут на небольшое число критичных сквозных сценариев вроде входа и покупки, потому что UI-тесты медленные и хрупкие в больших количествах. Обычно не окупается тестирование поведения фреймворков Apple и попиксельной вёрстки; снапшот-тесты тут помогают, но ломаются на каждой смене версии ОС, поэтому их держат мало и осознанно.

🦎

Прочитать ответы недостаточно

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

Пройти интервью Senior iOS (Swift) →
Бесплатно · 3 интервью в месяц

Другие уровни — iOS (Swift)

Junior iOS (Swift)Middle iOS (Swift)Все вопросы iOS (Swift)

Другие специализации

🔍Senior QA Manual🤖Senior QA AutomationSenior Java Backend🐍Senior Python Backend🐘Senior PHP Backend🦫Senior Go Backend🟢Senior Node.js Backend⚛️Senior React Frontend💚Senior Vue Frontend🅰️Senior Angular Frontend