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

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

Junior · без опыта / до 1 года

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

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

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

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

1

Какую проблему решают опционалы и как безопасно их разворачивать?

Ответ

Опционал делает «значения может не быть» частью типа, поэтому компилятор заставляет обработать пустой случай, а не падать в рантайме, как это делает нулевой указатель. Безопасное разворачивание — это if let или guard let, когда значение нужно дальше по коду, оператор ?? для значения по умолчанию и опциональная цепочка, если интересен только успешный путь. Force unwrap через ! — это обещание компилятору, что значение есть: допустимо для outlet-ов и ошибок программиста, но никогда для данных из сети.

2

В чём разница между struct и class в Swift? Что берёте по умолчанию?

Ответ

Struct — значимый тип: присваивание копирует его, наследования нет, и по возможности он размещается на стеке. Class — ссылочный тип с идентичностью, наследованием, deinit и накладными расходами ARC. Конвенция Swift — начинать со struct и переходить на class только когда нужна ссылочная семантика: разделяемое изменяемое состояние, совместимость с Objective-C или жизненный цикл, за которым нужно наблюдать.

3

Как работает ARC и из-за чего возникает retain cycle?

Ответ

ARC считает количество сильных ссылок на объект и освобождает его, когда счётчик обнуляется — это вставленные на этапе компиляции вызовы retain/release, а не сборщик мусора в рантайме. Retain cycle возникает, когда два объекта держат сильные ссылки друг на друга и ни один счётчик не доходит до нуля: классика — вью-контроллер владеет замыканием, которое сильно захватывает self. Разрывается через [weak self] или [unowned self] в списке захвата.

4

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

Ответ

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

5

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

Ответ

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

6

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

Ответ

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

7

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

Ответ

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

8

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

Ответ

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

9

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

Ответ

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

🦎

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

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

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

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

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

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

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