Как пройти собеседование по Swift: топ вопросов
Собеседование на позицию iOS-разработчика — это не только проверка знания фреймворков, но и глубокое понимание языка Swift. Работодатели хотят видеть кандидата, который разбирается в управлении памятью, конкурентности и особенностях синтаксиса. В этой статье мы собрали топ вопросов, которые часто задают на собеседованиях, с подробными ответами и примерами кода. Статья будет полезна как джуниорам, так и опытным разработчикам, желающим освежить знания перед интервью.
1. Основы Swift: типы, опционалы и управление памятью
Базовые вопросы проверяют, насколько хорошо вы понимаете фундаментальные концепции языка. Начнём с самого популярного — опционалов.
Вопрос 1: Что такое опционалы и зачем они нужны?
Ответ: Опционалы — это механизм безопасности типов, который позволяет переменной либо содержать значение, либо быть nil (отсутствие значения). Они решают проблему null-указателей, распространённую в других языках.
// Объявление опционала
var name: String? = "Анна"
name = nil // теперь переменная не содержит значения
// Безопасное извлечение (optional binding)
if let unwrappedName = name {
print("Привет, \(unwrappedName)")
} else {
print("Имя отсутствует")
}
// Принудительное извлечение (force unwrap) — опасно!
// let forcedName = name! // краш, если name == nil
Вопрос 2: В чём разница между struct и class?
Ответ: struct — это тип-значение (value type), а class — ссылочный тип (reference type). Структуры копируются при присваивании, классы передаются по ссылке. Кроме того, классы поддерживают наследование, а структуры — нет.
struct Point {
var x: Int
var y: Int
}
class Person {
var name: String
init(name: String) { self.name = name }
}
var pointA = Point(x: 1, y: 2)
var pointB = pointA // копия
pointB.x = 10
print(pointA.x) // 1 — оригинал не изменился
var personA = Person(name: "Иван")
var personB = personA // ссылка на тот же объект
personB.name = "Пётр"
print(personA.name) // "Пётр" — изменился
Вопрос 3: Как работает Automatic Reference Counting (ARC)?
Ответ: ARC автоматически подсчитывает количество сильных ссылок на объект класса. Когда счётчик достигает нуля, объект освобождается из памяти. Проблемы возникают при циклических ссылках (retain cycles), которые решаются с помощью weak или unowned ссылок.
class Parent {
var child: Child?
}
class Child {
weak var parent: Parent? // weak предотвращает retain cycle
}
var parent: Parent? = Parent()
var child: Child? = Child()
parent?.child = child
child?.parent = parent
2. Продвинутые концепции: замыкания, протоколы и дженерики
На следующем этапе интервьюер проверяет, умеете ли вы использовать функциональные возможности Swift.
Вопрос 4: Что такое замыкания (closures) и как они захватывают значения?
Ответ: Замыкание — это блок кода, который можно передавать и использовать как функцию. Оно захватывает (captures) переменные из окружающего контекста. Захват может быть сильным или слабым.
func makeIncrementer(incrementAmount: Int) -> () -> Int {
var total = 0
let incrementer: () -> Int = {
total += incrementAmount // захват total
return total
}
return incrementer
}
let incrementByTwo = makeIncrementer(incrementAmount: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
Вопрос 5: В чём разница между протоколом и абстрактным классом?
Ответ: В Swift нет абстрактных классов. Протокол определяет контракт (требования), который должны реализовать классы, структуры или перечисления. Протоколы могут иметь расширения с реализацией по умолчанию.
protocol Drivable {
var speed: Int { get set }
func drive()
}
struct Car: Drivable {
var speed: Int = 0
func drive() {
print("Машина едет со скоростью \(speed) км/ч")
}
}
Вопрос 6: Как работают дженерики (generics)?
Ответ: Дженерики позволяют писать гибкий и переиспользуемый код, который работает с любым типом. Они широко используются в стандартной библиотеке Swift (например, Array<Element>).
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var first = 10
var second = 20
swapTwoValues(&first, &second)
print(first, second) // 20 10
3. UIKit и архитектура iOS-приложений
Без знания UIKit собеседование по iOS невозможно. Здесь проверяют практический опыт.
Вопрос 7: Что такое MVC и в чём его недостатки?
Ответ: Model-View-Controller — это архитектурный паттерн, где Model отвечает за данные, View — за отображение, а Controller связывает их. Недостатки: Massive View Controller (контроллеры становятся слишком большими), сложность тестирования. Альтернативы: MVVM, VIPER, SwiftUI.
Вопрос 8: Как работает жизненный цикл UIViewController?
Ответ: Основные методы: viewDidLoad(), viewWillAppear(), viewDidAppear(), viewWillDisappear(), viewDidDisappear(). Порядок вызова зависит от того, как контроллер добавляется на экран.
override func viewDidLoad() {
super.viewDidLoad()
// Настройка UI, загрузка данных — вызывается один раз
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Обновление данных перед показом
}
Вопрос 9: Как избежать retain cycle в замыканиях при работе с UIKit?
Ответ: Используйте capture list с [weak self] внутри