декабря 21, 2025
12 мин. чтения

Вопросы для собеседования на позицию младшего iOS разработчика: Полное руководство

interview
career-advice
job-search
entry-level
Вопросы для собеседования на позицию младшего iOS разработчика: Полное руководство
MB

Milad Bonakdar

Автор

Освойте основы разработки под iOS с помощью важных вопросов для собеседования, охватывающих Swift, UIKit, SwiftUI, сохранение данных и архитектуру iOS-приложений для начинающих разработчиков.


Введение

Разработка под iOS стала одним из самых востребованных навыков в разработке мобильных приложений. Используя Swift в качестве основного языка и мощные фреймворки, такие как UIKit и SwiftUI, разработчики iOS создают опыт для миллионов пользователей по всему миру.

Это руководство охватывает основные вопросы для собеседования для начинающих iOS-разработчиков. Мы рассмотрим основы Swift, разработку пользовательского интерфейса, сохранение данных, работу с сетью и лучшие практики iOS, чтобы помочь вам подготовиться к вашей первой роли iOS-разработчика.


Основы Swift (6 вопросов)

1. В чем разница между var и let в Swift?

Ответ:

  • var: Объявляет изменяемую переменную. Ее значение можно изменить после инициализации.
  • let: Объявляет неизменяемую константу. После установки ее значение нельзя изменить.
  • Рекомендация: Используйте let по умолчанию для безопасности и ясности. Используйте var только тогда, когда вы знаете, что значение изменится.
let name = "John"  // Нельзя изменить
var age = 25       // Можно изменить
age = 26           // Допустимо
// name = "Jane"   // Ошибка: Нельзя присвоить значение

Распространенность: Очень часто Сложность: Легко


2. Объясните, что такое опционалы в Swift. Что такое опциональное связывание?

Ответ: Опционалы представляют значение, которое может быть nil (отсутствие значения).

  • Объявление: Используйте ? после типа: var name: String?
  • Методы извлечения:
    • Принудительное извлечение: name! (опасно, вызывает сбой, если nil)
    • Опциональное связывание: Безопасное извлечение с использованием if let или guard let
    • Объединение с nil: name ?? "Default"
    • Опциональная цепочка: user?.address?.city
var email: String? = "[email protected]"

// Опциональное связывание
if let unwrappedEmail = email {
    print("Email: \(unwrappedEmail)")
} else {
    print("No email")
}

// Инструкция Guard
guard let email = email else { return }
print(email)

Распространенность: Очень часто Сложность: Легко


3. В чем разница между class и struct в Swift?

Ответ:

  • Class: Тип ссылки (хранится в куче). Поддерживает наследование. Передается по ссылке.
  • Struct: Тип значения (хранится в стеке). Нет наследования. Передается по копии.
  • Когда использовать:
    • Struct: Для простых моделей данных, когда вам нужна семантика значения (независимые копии)
    • Class: Когда вам нужно наследование, семантика ссылки или деинициализаторы
struct Point {
    var x: Int
    var y: Int
}

class Person {
    var name: String
    init(name: String) { self.name = name }
}

var p1 = Point(x: 0, y: 0)
var p2 = p1  // Создана копия
p2.x = 10    // p1.x по-прежнему 0

var person1 = Person(name: "John")
var person2 = person1  // Та же ссылка
person2.name = "Jane"  // person1.name также "Jane"

Распространенность: Очень часто Сложность: Средне


4. Что такое замыкания в Swift?

Ответ: Замыкания — это самодостаточные блоки функциональности, которые можно передавать и использовать в вашем коде. Они похожи на лямбды или анонимные функции в других языках.

  • Синтаксис: { (параметры) -> ReturnType in statements }
  • Захват значений: Замыкания могут захватывать и хранить ссылки на переменные из своего окружающего контекста.
  • Общее использование: Обработчики завершения, обратные вызовы, операции с массивами.
// Простое замыкание
let greet = { (name: String) -> String in
    return "Hello, \(name)!"
}
print(greet("Alice"))

// Синтаксис завершающего замыкания
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }
print(doubled)  // [2, 4, 6, 8, 10]

Распространенность: Очень часто Сложность: Средне


5. Объясните разницу между weak и unowned ссылками.

Ответ: Оба используются для предотвращения циклов удержания (утечек памяти) в типах ссылок.

  • weak: Опциональная ссылка, которая автоматически становится nil, когда объект, на который она ссылается, освобождается. Используйте, когда ссылка может пережить объект.
  • unowned: Неопциональная ссылка, которая предполагает, что объект всегда будет существовать. Вызывает сбой при доступе после освобождения. Используйте, когда вы уверены, что ссылка не переживет объект.
class Person {
    var name: String
    weak var apartment: Apartment?  // weak для предотвращения цикла удержания
    init(name: String) { self.name = name }
}

class Apartment {
    var unit: String
    unowned let tenant: Person  // unowned - у квартиры всегда есть жилец
    init(unit: String, tenant: Person) {
        self.unit = unit
        self.tenant = tenant
    }
}

Распространенность: Часто Сложность: Средне


6. Что такое протоколы в Swift?

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

  • Похоже на: Интерфейсы в других языках
  • Расширения протоколов: Могут предоставлять реализации по умолчанию
  • Протокол-ориентированное программирование: Предпочтительная парадигма Swift
protocol Drawable {
    func draw()
}

struct Circle: Drawable {
    var radius: Double
    
    func draw() {
        print("Drawing circle with radius \(radius)")
    }
}

struct Rectangle: Drawable {
    var width: Double
    var height: Double
    
    func draw() {
        print("Drawing rectangle \(width)x\(height)")
    }
}

Распространенность: Очень часто Сложность: Легко


Основы UIKit (5 вопросов)

7. В чем разница между UIView и UIViewController?

Ответ:

  • UIView: Представляет прямоугольную область на экране. Обрабатывает рисование и обработку событий. Примеры: UILabel, UIButton, UIImageView.
  • UIViewController: Управляет иерархией представлений. Обрабатывает жизненный цикл представления, взаимодействие с пользователем и навигацию. Содержит одно корневое представление и управляет его подпредставлениями.
  • Взаимосвязь: Контроллер представления управляет представлениями. У одного контроллера представления может быть много представлений.

Распространенность: Очень часто Сложность: Легко


8. Объясните методы жизненного цикла контроллера представления.

Ответ: Контроллеры представления имеют определенные методы жизненного цикла, вызываемые по порядку:

  1. viewDidLoad(): Вызывается один раз, когда представление загружается в память. Настройка, которая должна произойти один раз.
  2. viewWillAppear(_:): Вызывается перед появлением представления на экране. Может вызываться несколько раз.
  3. viewDidAppear(_:): Вызывается после появления представления на экране. Запускайте анимацию здесь.
  4. viewWillDisappear(_:): Вызывается перед исчезновением представления.
  5. viewDidDisappear(_:): Вызывается после исчезновения представления. Очистите ресурсы.
override func viewDidLoad() {
    super.viewDidLoad()
    // Одноразовая настройка: настройка пользовательского интерфейса, загрузка данных
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // Обновление данных, начало прослушивания уведомлений
}

Распространенность: Очень часто Сложность: Легко


9. Что такое Auto Layout и как вы используете constraints?

Ответ: Auto Layout — это система макетов на основе ограничений, которая позволяет создавать адаптивные пользовательские интерфейсы, работающие на экранах разных размеров и ориентаций.

  • Constraints: Определите взаимосвязи между представлениями (ширина, высота, расстояние, выравнивание)
  • Методы:
    • Interface Builder: Визуальный редактор в Xcode
    • Программно: NSLayoutConstraint или NSLayoutAnchor API
    • Visual Format Language: На основе строк (сейчас менее распространен)
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)

NSLayoutConstraint.activate([
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    button.widthAnchor.constraint(equalToConstant: 200),
    button.heightAnchor.constraint(equalToConstant: 50)
])

Распространенность: Очень часто Сложность: Средне


10. В чем разница между frame и bounds?

Ответ:

  • frame: Расположение и размер представления в системе координат его суперпредставления. Используется для позиционирования представления.
  • bounds: Расположение и размер представления в его собственной системе координат. Начало координат обычно (0, 0). Используется для рисования содержимого внутри представления.
  • Ключевое различие: frame относится к родителю, bounds относится к самому себе.
let view = UIView(frame: CGRect(x: 50, y: 100, width: 200, height: 150))
print(view.frame)   // (50, 100, 200, 150) - положение в суперпредставлении
print(view.bounds)  // (0, 0, 200, 150) - собственная система координат

Распространенность: Часто Сложность: Средне


11. Как вы обрабатываете ввод пользователя из UITextField?

Ответ: Существует несколько подходов:

  • Target-Action: Добавьте цель для события .editingChanged
  • Delegate: Соответствует протоколу UITextFieldDelegate
  • Combine: Используйте издателей (современный подход)
class ViewController: UIViewController, UITextFieldDelegate {
    let textField = UITextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Подход Delegate
        textField.delegate = self
        
        // Подход Target-Action
        textField.addTarget(self, action: #selector(textChanged), for: .editingChanged)
    }
    
    @objc func textChanged(_ textField: UITextField) {
        print("Text: \(textField.text ?? "")")
    }
    
    // Метод Delegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}

Распространенность: Очень часто Сложность: Легко


Основы SwiftUI (4 вопроса)

12. Что такое SwiftUI и чем он отличается от UIKit?

Ответ: SwiftUI — это декларативный фреймворк пользовательского интерфейса Apple, представленный в iOS 13.

  • UIKit: Императивный (вы говорите системе, как строить пользовательский интерфейс шаг за шагом). Зрелый, широко используется.
  • SwiftUI: Декларативный (вы описываете, как должен выглядеть пользовательский интерфейс). Современный, меньше кода, автоматические обновления.
  • Ключевые особенности:
    • Живой предварительный просмотр в Xcode
    • Кроссплатформенность (iOS, macOS, watchOS, tvOS)
    • Обновления пользовательского интерфейса, управляемые состоянием
    • Встроенная анимация
// SwiftUI
struct ContentView: View {
    @State private var count = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
            Button("Increment") {
                count += 1
            }
        }
    }
}

Распространенность: Очень часто Сложность: Легко


13. Объясните @State, @Binding и @ObservedObject в SwiftUI.

Ответ: Это обертки свойств для управления состоянием в SwiftUI:

  • @State: Частное состояние, принадлежащее представлению. При его изменении представление перерисовывается.
  • @Binding: Создает двустороннее соединение со свойством @State, принадлежащим родительскому представлению.
  • @ObservedObject: Ссылается на внешний объект (класс, соответствующий ObservableObject). Представление обновляется, когда изменяются свойства @Published объекта.
class UserData: ObservableObject {
    @Published var name = ""
}

struct ParentView: View {
    @State private var isOn = false
    @ObservedObject var userData = UserData()
    
    var body: some View {
        VStack {
            ChildView(isOn: $isOn)  // Передать связывание
            Text(userData.name)
        }
    }
}

struct ChildView: View {
    @Binding var isOn: Bool  // Получает связывание
    
    var body: some View {
        Toggle("Switch", isOn: $isOn)
    }
}

Распространенность: Часто Сложность: Средне


14. Как создать список в SwiftUI?

Ответ: Используйте представление List для отображения прокручиваемых коллекций данных.

struct ContentView: View {
    let fruits = ["Apple", "Banana", "Orange", "Grape"]
    
    var body: some View {
        List(fruits, id: \.self) { fruit in
            Text(fruit)
        }
    }
}

// С пользовательской моделью
struct Task: Identifiable {
    let id = UUID()
    let title: String
}

struct TaskListView: View {
    let tasks = [
        Task(title: "Buy groceries"),
        Task(title: "Walk the dog")
    ]
    
    var body: some View {
        List(tasks) { task in
            Text(task.title)
        }
    }
}

Распространенность: Часто Сложность: Легко


15. Что такое модификаторы представления в SwiftUI?

Ответ: Модификаторы представления — это методы, которые создают новое представление с измененными свойствами. Их можно объединять в цепочку.

  • Общие модификаторы: .padding(), .background(), .foregroundColor(), .font(), .frame()
  • Порядок имеет значение: Модификаторы применяются последовательно
Text("Hello, World!")
    .font(.title)
    .foregroundColor(.blue)
    .padding()
    .background(Color.yellow)
    .cornerRadius(10)
    .shadow(radius: 5)

// Пользовательский модификатор
struct PrimaryButtonStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
    }
}

extension View {
    func primaryButton() -> some View {
        modifier(PrimaryButtonStyle())
    }
}

Распространенность: Часто Сложность: Легко


Данные и работа с сетью (5 вопросов)

16. Как сделать сетевой запрос в iOS?

Ответ: Используйте URLSession для сетевых задач.

func fetchData() {
    guard let url = URL(string: "https://api.example.com/data") else { return }
    
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            print("Error: \(error)")
            return
        }
        
        guard let data = data else { return }
        
        // Разбор JSON
        do {
            let decoder = JSONDecoder()
            let result = try decoder.decode(MyModel.self, from: data)
            print(result)
        } catch {
            print("Decoding error: \(error)")
        }
    }
    
    task.resume()
}

Распространенность: Очень часто Сложность: Средне


17. Что такое Codable в Swift?

Ответ: Codable — это псевдоним типа для протоколов Encodable & Decodable. Это позволяет легко преобразовывать типы Swift во внешние представления, такие как JSON.

  • Автоматический синтез: Swift автоматически генерирует код кодирования/декодирования, если все свойства являются Codable.
  • Пользовательские ключи: Используйте перечисление CodingKeys для сопоставления разных имен свойств.
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

// Декодирование JSON
let json = """
{
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]"
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let user = try decoder.decode(User.self, from: json)

// Кодирование в JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let jsonData = try encoder.encode(user)

Распространенность: Очень часто Сложность: Легко


18. Как вы локально сохраняете данные в iOS?

Ответ: Несколько вариантов для локального сохранения данных:

  • UserDefaults: Простое хранилище ключ-значение для небольших объемов данных (настройки, предпочтения)
  • Файловая система: Сохраните файлы в каталог Documents или Cache
  • Core Data: Фреймворк Apple для управления и сохранения графа объектов
  • SQLite: Реляционная база данных
  • Keychain: Безопасное хранилище для конфиденциальных данных (пароли, токены)
// UserDefaults
UserDefaults.standard.set("John", forKey: "username")
let username = UserDefaults.standard.string(forKey: "username")

// Файловая система
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filePath = documentsPath.appendingPathComponent("data.json")

// Запись
try data.write(to: filePath)

// Чтение
let loadedData = try Data(contentsOf: filePath)

Распространенность: Очень часто Сложность: Легко


19. В чем разница между синхронными и асинхронными операциями?

Ответ:

  • Синхронные: Блокируют текущий поток до завершения операции. Может заморозить пользовательский интерфейс, если запустить в основном потоке.
  • Асинхронные: Не блокируют поток. Операция выполняется в фоновом режиме, и по завершении вызывается обработчик завершения.
  • Основной поток: Обновления пользовательского интерфейса должны происходить в основном потоке. Используйте DispatchQueue.main.async для переключения в основной поток.
// Синхронные (ПЛОХО для сетевых вызовов)
let data = try Data(contentsOf: url)  // Блокирует до завершения

// Асинхронные (ХОРОШО)
URLSession.shared.dataTask(with: url) { data, response, error in
    // Это запускается в фоновом потоке
    
    DispatchQueue.main.async {
        // Обновление пользовательского интерфейса в основном потоке
        self.label.text = "Data loaded"
    }
}.resume()

Распространенность: Часто Сложность: Легко


20. Что такое Grand Central Dispatch (GCD)?

Ответ: GCD — это низкоуровневый API Apple для управления параллельными операциями.

  • Dispatch Queues: Очереди FIFO, которые выполняют задачи последовательно или параллельно
  • Main Queue: Последовательная очередь для обновления пользовательского интерфейса
  • Global Queues: Параллельные очереди с разными приоритетами (background, utility, userInitiated)
// Запустить в фоновом потоке
DispatchQueue.global(qos: .background).async {
    // Тяжелые вычисления
    let result = performExpensiveOperation()
    
    // Обновление пользовательского интерфейса в основном потоке
    DispatchQueue.main.async {
        self.label.text = result
    }
}

// Задержка выполнения
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    print("Executed after 2 seconds")
}

Распространенность: Часто Сложность: Средне


Newsletter subscription

Еженедельные советы по карьере, которые действительно работают

Получайте последние идеи прямо на вашу почту

Похожие посты

Decorative doodle

Ваше следующее собеседование — всего одно резюме

Создайте профессиональное оптимизированное резюме за несколько минут. Не нужны навыки дизайна—только проверенные результаты.

Создать моё резюме

Поделиться этим постом

Преодолейте 75% Уровень Отказа ATS

3 из 4 резюме никогда не доходят до человеческих глаз. Наша оптимизация ключевых слов повышает ваш процент прохождения до 80%, гарантируя, что рекрутеры действительно увидят ваш потенциал.