Skip to content

Вопросы на собеседовании: Swift-разработчик

100 реальных вопросов с образцовыми ответами и пояснениями для уровня iOS-разработчик.

Смотреть пример резюме: Swift-разработчик

Тренировка флешкарточками

Интервальное повторение · Hunter Pass

Вопросы

let создаёт неизменяемую привязку, а значение, объявленное через var, можно менять.

  • Предпочитайте let: тогда случайное повторное присваивание станет ошибкой компиляции.
  • Используйте var для счётчика или суммы, которые должны изменяться.
  • В Array, объявленный через let, нельзя добавить элемент с помощью append, а в Array через var можно.

Зачем это спрашивают: Вопрос проверяет понимание неизменяемых и изменяемых привязок в Swift.

type-inference

Swift определяет по литералу тип Int, поэтому явно указывать тип не нужно.

  • Выведенный тип фиксируется во время компиляции.
  • Напишите : Int64, если API требует именно этот тип.
  • Попытка позже присвоить несовместимое значение всё равно приведёт к ошибке компиляции.

Зачем это спрашивают: Вопрос проверяет понимание статического вывода типов.

Swift требует явного преобразования, потому что при сужении типа часть данных может потеряться.

  • Int(3.8) намеренно отбрасывает дробную часть.
  • Проверяйте границы диапазона, если входное число может оказаться слишком большим.
  • Для вычислений с дробной частью преобразуйте Int в Double.

Зачем это спрашивают: Вопрос проверяет понимание безопасной работы с числовыми типами.

reference-semantics

При присваивании значения создаётся независимая копия, а при присваивании ссылки две переменные указывают на один экземпляр.

  • struct, enum, Array и Dictionary имеют семантику значений.
  • Экземпляры class имеют ссылочную семантику.
  • Изменение одной копии структуры не влияет на другую.

Зачем это спрашивают: Вопрос проверяет понимание поведения значимых и ссылочных типов.

copy-on-write

Копии Array могут использовать общее хранилище, пока одну из них не изменят.

  • При присваивании обычно не происходит немедленного копирования каждого элемента.
  • При первом изменении для этой копии при необходимости создаётся отдельное хранилище.
  • Внешне Array всё равно ведёт себя как значимый тип.

Зачем это спрашивают: Вопрос проверяет понимание механизма copy-on-write.

swiftoptionals

Optional хранит либо значение заданного типа, либо nil.

  • Int? является сокращённой записью Optional<Int>.
  • Там, где требуется обычный Int, опциональное значение нужно извлечь.
  • Так можно представить отсутствие данных без условных значений вроде -1.

Зачем это спрашивают: Вопрос проверяет понимание опциональных значений.

swiftoptionalsswiftui

Ветка if let выполняется, только если опциональное значение не равно nil.

  • При nil условие просто не выполняется, и приложение не падает.
  • Внутри ветки связанное имя имеет уже не опциональный тип.
  • Ветка else позволяет явно обработать отсутствие значения.

Зачем это спрашивают: Вопрос проверяет понимание безопасного извлечения опциональных значений.

control-flowoptional-binding

guard let удобен для проверки условия, при нарушении которого функция должна сразу завершить текущий путь.

  • Блок else должен выполнить return, throw, break или continue.
  • Извлечённое значение остаётся доступным после guard.
  • Основной успешный сценарий не приходится помещать в глубокую вложенность.

Зачем это спрашивают: Вопрос проверяет выбор конструкции для управления потоком с опциональными значениями.

indexes

String использует String.Index, потому что один Character может состоять из нескольких скаляров Unicode.

  • startIndex указывает на первую допустимую границу символа.
  • index(after:) переводит индекс к следующей допустимой границе.
  • Для небольших задач можно использовать Array(string), но это потребует дополнительной памяти.

Зачем это спрашивают: Вопрос проверяет понимание безопасной работы со строками Unicode.

Array хранит упорядоченные элементы, Set только уникальные элементы, а Dictionary сопоставляет ключи со значениями.

  • Array допускает повторы и доступ по позиции.
  • Set подходит для быстрой проверки наличия элемента, когда порядок не важен.
  • Обращение к Dictionary возвращает опциональное значение, потому что ключ может отсутствовать.

Зачем это спрашивают: Вопрос проверяет умение выбрать подходящую коллекцию.

Кортеж объединяет фиксированный набор связанных значений без объявления нового именованного типа.

  • Имена полей делают запись (code: 200, message: "OK") понятной.
  • Функция может вернуть два небольших результата одним кортежем.
  • Если данным нужны методы или многократное использование, лучше объявить struct.

Зачем это спрашивают: Вопрос проверяет понимание назначения кортежей.

Диапазон a...b включает b, а a..<b не включает его.

  • 1...3 содержит 1, 2 и 3.
  • 0..<array.count соответствует обычным целочисленным индексам массива.
  • Если индекс не нужен, лучше перебирать сами элементы.

Зачем это спрашивают: Вопрос проверяет понимание границ диапазонов.

Для небольшого одноразового результата функция может вернуть именованный кортеж.

  • Возвращаемый тип можно записать как (min: Int, max: Int).
  • Вызывающий код обращается к полям через result.min и result.max.
  • Если результат становится частью предметной модели, лучше использовать struct.

Зачем это спрашивают: Вопрос проверяет способы возврата нескольких значений из функции.

Метки аргументов поясняют назначение параметров в месте вызова функции.

  • Вызов move(from: 1, to: 3) читается как фраза.
  • Внутреннее имя параметра может отличаться от его метки.
  • Используйте _ только тогда, когда вызов без метки остаётся понятным.

Зачем это спрашивают: Вопрос проверяет понимание меток аргументов.

Значение по умолчанию позволяет не передавать необязательный аргумент и при этом сохранить одну реализацию функции.

  • В greet(name:punctuation:) для punctuation можно задать значение "!".
  • Явно переданный аргумент заменяет значение по умолчанию.
  • Обязательные для логики данные не следует скрывать за значением по умолчанию.

Зачем это спрашивают: Вопрос проверяет понимание параметров со значениями по умолчанию.

inout позволяет функции изменить переменную, переданную вызывающим кодом.

  • В объявлении inout ставится перед типом параметра.
  • При вызове используется &, например increment(&count).
  • Константу let передать нельзя, потому что функция должна изменить значение.

Зачем это спрашивают: Вопрос проверяет понимание изменения аргументов через inout.

closures

Замыкание представляет исполняемый код, который можно хранить и передавать как значение.

  • Оно может захватывать имена из окружающей области видимости.
  • Методы map и filter принимают замыкания.
  • Синтаксис завершающего замыкания позволяет вынести его за круглые скобки.

Зачем это спрашивают: Вопрос проверяет базовое понимание замыканий.

escaping-closures

@escaping означает, что замыкание-параметр может продолжить существовать после завершения вызова функции.

  • Сохраняемые обработчики завершения обычно требуют @escaping.
  • Обычное неубегающее замыкание выполняется во время вызова функции.
  • В убегающем замыкании при захвате экземпляра нужно явно писать self.

Зачем это спрашивают: Вопрос проверяет понимание убегающих замыканий.

enums

Исходное значение задаёт каждому case одно постоянное значение общего простого типа.

  • В enum Direction: String каждому варианту можно назначить строковое значение.
  • Инициализатор init(rawValue:) возвращает опциональное значение, потому что входные данные могут не совпасть ни с одним case.
  • Исходное значение объявляется один раз, а не передаётся при создании каждого экземпляра.

Зачем это спрашивают: Вопрос проверяет понимание исходных значений у перечислений.

Связанные значения добавляют данные времени выполнения к конкретному case перечисления.

  • Разные варианты могут хранить значения разных типов, например success(Data).
  • Шаблон в switch позволяет извлечь связанное значение.
  • Исходные значения постоянны, а связанные могут отличаться у разных экземпляров.

Зачем это спрашивают: Вопрос проверяет различие между связанными и исходными значениями enum.

Закрытые вопросы

  • 21

    Когда стоит выбрать struct вместо class?

    swiftvalue-typesreference-types
  • 22

    Чем хранимые свойства отличаются от вычисляемых?

  • 23

    Что такое willSet и didSet?

  • 24

    Почему методу структуры иногда нужен mutating?

    swiftvalue-typesmutation
  • 25

    За что отвечает инициализатор?

  • 26

    Что определяет протокол?

    typingprotocols
  • 27

    Что можно добавить с помощью extension?

    extensions
  • 28

    Зачем использовать обобщённую функцию вместо Any?

    generics
  • 29

    Как вместе работают throws, try и do-catch?

    error-handling
  • 30

    Когда полезен Result?

    result-type
  • 31

    Что делает defer?

    resource-cleanup
  • 32

    Чем управляет ARC?

    memory
  • 33

    Чем отличаются weak и unowned?

    memorymemory-management
  • 34

    Что предоставляет Codable?

    codableserialization
  • 35

    Как CodingKeys помогает при работе с JSON?

    serialization
  • 36

    Что представляют URL, Data и Date в Foundation?

  • 37

    Чем отличаются private, fileprivate, internal и public?

  • 38

    Что такое модуль Swift и что делает import?

    swiftmodules
  • 39

    Что означают package, target и product в SPM?

    swift-package-manager
  • 40

    Что означают async и await?

    asyncconcurrency
  • 41

    Для чего используется Task?

    structured-concurrency
  • 42

    Что гарантирует @MainActor?

    actor-isolation
  • 43

    Какую проблему решает actor?

    concurrency
  • 44

    Что выражает Sendable?

    concurrency
  • 45

    Как устроен простой тест XCTest?

    xctestswiftvalue-types
  • 46

    Для чего нужны setUp и tearDown?

  • 47

    Где проходит граница между SwiftUI View и состоянием?

    swiftuiswift
  • 48

    Чем отличаются SwiftUI и UIKit?

    uikitswiftuiswift
  • 49

    Как консольная программа на Swift может прочитать аргументы процесса?

    concurrencyswift
  • 50

    Что делает простой маршрут в Vapor?

    server-side
  • 51

    Int("abc") возвращает nil. Как консольная программа должна сообщить о неверном вводе?

  • 52

    Принудительное извлечение приводит к падению, если поля нет в JSON. Что нужно изменить?

  • 53

    Если nickname отсутствует, нужно показать "Guest". Какое выражение с Optional подойдёт?

    swiftoptionals
  • 54

    При декодировании возникает keyNotFound для поля, которое иногда отсутствует. Как исправить модель?

  • 55

    JSON содержит "age": "20", а в модели используется Int. Почему декодирование завершается ошибкой?

  • 56

    В JSON используется user_id, а в Swift свойство называется userID. Как локально исправить keyNotFound?

    swift
  • 57

    Удаление элементов Array во время обхода старых индексов приводит к падению. Как переписать код?

  • 58

    Почему counts[word] += 1 не компилируется для Dictionary?

  • 59

    После var b = a добавление элемента в Array b не меняет a. Это ожидаемое поведение?

  • 60

    После let b = a для экземпляра class изменение b.name также меняет a.name. Почему?

    reference-types
  • 61

    text[0] приводит к ошибке компиляции. Как прочитать первый Character?

  • 62

    Сохранённое замыкание выводит последнее значение counter, а не значение на момент создания. Как захватить снимок?

    closuressnapshot
  • 63

    Обратный вызов с @escaping требует явно указать self для свойства. Чего добивается компилятор?

    callbacksescaping-closures
  • 64

    Контроллер не деинициализируется после сохранения замыкания, которое использует self. В чём вероятная причина?

    closures
  • 65

    Обратный вызов с [weak self] при выполнении получает nil. Всегда ли это ошибка?

    callbacksmemory
  • 66

    Тип не выполняет требование протокола к свойству get-set. Что он должен предоставить?

    typingprotocols
  • 67

    Протокол Resettable требует mutating func reset(), но reset у struct получает ошибку "self is immutable" на count = 0. Как это исправить?

    immutabilitytypingswift
  • 68

    Обобщённая функция maximum не может применить > к T без ограничений. Чего не хватает?

    generics
  • 69

    Для readFile() компилятор сообщает, что вызов функции с ошибкой не помечен try. Какие есть варианты?

  • 70

    Общий catch скрывает известный случай invalidInput. Как сохранить его сообщение?

  • 71

    Функция выводит ошибку, а вызывающий код продолжает работу так, будто всё удалось. Что нужно изменить?

  • 72

    Дескриптор файла остаётся открытым, если разбор данных бросает ошибку. Что гарантирует очистку?

    error-handling
  • 73

    Для асинхронного вызова компилятор сообщает, что он не помечен await. Что требуется?

    asyncconcurrency
  • 74

    Синхронный обработчик кнопки должен вызвать async load(). Какое небольшое изменение исправит границу?

    asynccallbacksconcurrency
  • 75

    Отмена Task не останавливает долгий цикл. Чего не хватает?

    structured-concurrency
  • 76

    Две задачи увеличивают счётчик, но итоговое значение оказывается слишком маленьким. Как поможет actor?

    concurrency
  • 77

    Чтение counter.value за пределами actor приводит к ошибке изоляции. Что должен сделать вызывающий код?

    concurrency
  • 78

    Асинхронная работа обновляет состояние интерфейса и вызывает предупреждение об actor. Как это исправить?

    asyncconcurrencystate
  • 79

    Захват изменяемого экземпляра class в замыкании @Sendable вызывает предупреждение. Какое простое безопасное решение подойдёт?

    closuresconcurrencyreference-types
  • 80

    Два независимых асинхронных запроса выполняются последовательно. Как запустить оба до ожидания результатов?

    asyncconcurrency
  • 81

    Тесту XCTest нужно значение из async loadName(). Какая сигнатура подойдёт?

    asyncconcurrencytesting
  • 82

    parse("bad") должна бросить ошибку. Как проверить это в XCTest?

    xctest
  • 83

    Тест проходит отдельно, но падает после того, как другой тест изменил singleton. Что исправить первым?

  • 84

    SPM сообщает no such module Utility, хотя цель существует. Что проверить сначала?

    swift-package-managermodules
  • 85

    Продукт называется ToolsKit, а модуль ToolsCore. Какое имя нужно указать в import?

    modules
  • 86

    SPM ожидает исходные файлы AppCLI в Sources/AppCLI. Какие два исправления допустимы?

    swift-package-manager
  • 87

    FileManager не находит config.json из консольной программы. Как проверить путь?

    configfile-system
  • 88

    Консольная программа для JSON выводит только "decode failed". Как показать полезную причину?

  • 89

    CLI падает на CommandLine.arguments[1], если аргументов нет. Каково минимальное исправление?

  • 90

    ArgumentParser требует --input, но пользователь не передаёт этот параметр. Что должно произойти?

    argument-parser
  • 91

    ArgumentParser получает --count many для Int. На каком этапе должна возникнуть ошибка?

    argument-parser
  • 92

    GET /users возвращает 404, но в Vapor зарегистрирован app.post. В чём ошибка?

    server-side
  • 93

    Маршрут Vapor /users/:id совпал с /users/abc, но обработчику нужен id типа Int. Какой ответ и какое исправление верны?

    server-side
  • 94

    Vapor POST получает некорректный JSON для Content. Что должен сделать обработчик?

    server-side
  • 95

    Запрос Vapor принимает пустой username и позже завершается ошибкой. Где нужно выполнять проверку?

    validationserver-side
  • 96

    Поиск Vapor возвращает nil для пользователя 42. Какой статус лучше пустого ответа 200?

    server-side
  • 97

    Асинхронный обработчик Vapor вызывает сервис с ошибкой без try await. Что требуется?

    asyncconcurrencyserver-side
  • 98

    Кнопка SwiftUI меняет локальный var внутри body, но текст не обновляется. Что требуется?

    swiftuiswift
  • 99

    SwiftUI List теряет строки, потому что элементы имеют одинаковый id. Что нужно изменить?

    swiftuiswift
  • 100

    Переиспользуемая UITableViewCell на мгновение показывает асинхронно загруженное изображение предыдущей строки. Как это исправить?

    asyncconcurrencyuikit