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