Должен ли оператор switch в Swift обрабатывать все кейсы enum?

Ответ

Да, в Swift оператор switch должен быть исчерпывающим (exhaustive) при работе с перечислениями (enum). Компилятор проверяет это и выдает ошибку, если не все кейсы обработаны.

Правила и исключения:

  1. Обычный enum: Необходимо явно перечислить все кейсы или добавить ветку default.

    enum Direction {
        case north, south, east, west
    }
    
    let dir = Direction.north
    switch dir {
        case .north: print("North")
        case .south: print("South")
        case .east: print("East")
        case .west: print("West")
        // default не требуется, все кейсы обработаны
    }
  2. @unknown default: Используется для enum, помеченных как @frozen (или стандартных библиотечных), которые не будут меняться в будущем, и для незамороженных (non-frozen) enum из фреймворков, которые могут получить новые кейсы в следующих версиях OS. Эта ветка обрабатывает любые потенциальные будущие кейсы, не нарушая исчерпывающую проверку компилятора.

    // Для non-frozen enum из фреймворка (например, UITableViewCell.CellStyle)
    switch cellStyle {
        case .default: // Обработка известных кейсов
        case .value1:
        case .value2:
        @unknown default: // Обрабатывает любые новые кейсы, добавленные в будущем
            break
    }

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

Ответ 18+ 🔞

О, смотри-ка, какой у нас тут академический вопрос подъехал! Swift и его switch, который как будто занудный препод в универе: «А ты все кейсы перечислил? А ну-ка покажи!»

Так вот, слушай сюда, этот ваш оператор switch — он реально исчерпывающий должен быть, когда дело доходит до enum. Компилятор, сука, стоит над душой как злой участковый и проверяет: «А все ли случаи, пидорок, обработал?» Не обработал — получай ошибку и иди нахуй переделывать.

Как это работает, а главное — когда оно ломается:

  1. Обычный enum, домашний, ручной работы: Тут всё просто, как три копейки. Либо ты в switch перечисляешь ВСЕ возможные варианты, либо, если тебе лень и ты распиздяй, пишешь default — и компилятор отстаёт.

    enum Direction {
        case north, south, east, west // Четыре стороны, и ни хуя больше
    }
    
    let dir = Direction.north
    switch dir {
        case .north: print("На север, епта!")
        case .south: print("На юг, блядь")
        case .east: print("На восток")
        case .west: print("На запад")
        // default тут не нужен, потому что мы и так всё перебрали. Компилятор доволен.
    }
  2. А вот тут начинается магия, блядь — @unknown default: Это, сука, специальная штука для enum'ов, которые живут не в твоём коде. Бывают они двух видов:

    • @frozen (замороженные) — это те, которые больше меняться не будут. Их из стандартной библиотеки.
    • non-frozen (незамороженные) — это те, которые живут в чужих фреймворках (например, от Apple). И какая-нибудь новая версия iOS может прийти и сказать: «А мы тут новый кейсик добавили, получайте!»

    Вот чтобы твой код не сломался в хлам, когда такое произойдёт, и нужен @unknown default. Он как страховка от ебучего сюрприза. Ты обрабатываешь все известные на сейчас кейсы, а на будущее говоришь: «Ладно, на всё остальное — похуй, просто пропусти».

    // Допустим, это какой-то стиль ячейки из UIKit (он non-frozen)
    switch cellStyle {
        case .default: // Обрабатываем то, что знаем
        case .value1:
        case .value2:
        @unknown default: // А это — затычка на случай, если Apple в будущем подкинет ещё какой-нибудь .value3Supreme
            break // Идём нахуй и ничего не делаем, но хотя бы не падаем!
    }

А зачем весь этот цирк, спросишь? А затем, чувак, чтобы у тебя в продакшене не вылезла ошибка на ровном месте, потому что ты какой-то кейс хуй забыл. Компилятор заставляет тебя думать головой на этапе написания кода, а не когда пользователи уже тебе в личку пишут: «Приложение, блядь, сломалось!». Это, можно сказать, защита от самого себя, от своей же распиздяйскости.