Оператор switch в Swift: синтаксис и примеры использования

Оператор swich позволяет проверить определенное значение и сравнить его с несколькими условиями. Это особенно эффективно для принятия решений на основе переменной, которая может содержать ряд возможных значений. Использование оператора switch позволяет использовать более краткий и удобный синтаксис кода.

Что из себя представляет оператор switch?

Оператор switch проверяет значение и сравнивает его с несколькими возможными шаблонами.

Рассмотрим следующее перечисление:

enum Compass {
    case north
    case east
    case south
    case west
}

Если вы хотите найти нужное направление, вы можете использовать следующий код:

let heading = Compass.south
 
if heading == .north {
    print("Вы направляетесь на север!")
} else if heading == .east {
    print("Вы направляетесь на восток!")
} else if heading == .south {
    print("Вы направляетесь на юг!")
} else if heading == .west {
    print("Вы направляетесь на запад!")
}

Приведенный выше код использует оператор if для оценки значения heading и вывода соответствующей строки текста.

Мы можем сделать то же самое, используя оператор switch:

switch heading {
case .north:
    print("Вы направляетесь на север!")
case .east:
    print("Вы направляетесь на восток!")
case .south:
    print("Вы направляетесь на юг!")
case .west:
    print("Вы направляетесь на запад!")
}

Сначала мы используем ключевое слово switch, а затем проверяемое выражение, в данном случае это константа heading. Это значение, которое рассматривается блоками switch. Затем мы перебираем возможные варианты значений с помощью case. В приведенном выше примере мы рассматриваем все возможные значения перечисления Compass.

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

switch heading {
case .north:
    print("Вы направляетесь на север!")
case .south:
    print("Вы направляетесь на юг!")
case .west:
    print("Вы направляетесь на запад!")
}
 
// error: switch must be exhaustive

Особенности работы с оператором switch

Даже если заявление со switch должно быть исчерпывающим, вам не нужно явно указывать каждый параметр.

Рассмотрим перечисление Authorization:

enum Authorization {
    case granted
    case undetermined
    case unauthorized
    case denied
    case restricted
}

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

switch state {
case .granted:
    print("Доступ разрешен.")
default:
    print("Доступ закрыт!")
}

В приведенном выше коде парамтер default используется для ответа на любой необработанный случай. Это делает выражение со switch исчерпывающим.

Вы также можете проверить более сложные случаи:

switch state {
case .granted:
    print("Доступ разрешен.")
case .undetermined:
    print("Предоставьте код доступа.")
case .unauthorized, .denied, .restricted:
    print("Доступ закрыт!")
}

Последний случай объединяет несколько случаев в одной строке.

Для того, чтобы было выполнено несколько условий, вы можете использовать оператор fallthrough:

var message = "Ответ: "
let state = Authorization.undetermined
 
switch state {
case .granted:
    message += "Доступ открыт. Вы можете продолжить"
case .undetermined:
    message += "Предоставьте код доступа."
    fallthrough
default:
    message += "Доступ закрыт!"
}
 
print(message)
// Output: Ответ: Предоставьте код доступа. Доступ закрыт!

В приведенном выше примере выполняется как условие .undetermined, так и default.

Проверка диапазонов с помощью switch

Вы можете использовать операторы switch для проверки интервалов и диапазонов.

Рассмотрим, например, как люди воспринимают видимый свет с разными длинами волн:

let wavelength = 620
 
switch wavelength {
case 380..<450:
    print("Пурпурный!")
case 450..<495:
    print("Синий!")
case 495..<570:
    print("Зеленый!")
case 570..<590:
    print("Желтый!")
case 590..<620:
    print("Оранжевый!")
case 620..<750:
    print("Красный!")
default:
    print("Не видимый спектр!")
}

Для каждого диапазона длины волны мы определяем интервал с оператором полуоткрытого диапазона.

Оператор switch и кортежи

Вы можете использовать оператор switch с кортежами.

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

let flight = (747, "SFO")

Тип константы flight (Int, String). После определения кортежа вы не можете изменить его порядок или тип. Кортежи идеально подходят для передачи нескольких связанных значений в одну переменную.

Вы можете получить доступ к значениям кортежа с помощью индекса:

print(flight.1)
// Output: SFO

Также можно использовать значения кортежа:

let flight = (airplane: 747, airport: "SFO")
print(flgith.airplane)
// Output: 747

Мы можем использовать кортежи вместе с оператором switch:

for i in 1...100 {
    switch (i % 3 == 0, i % 5 == 0) {
    case (true, false):
        print("Fizz")
    case (false, true):
        print("Buzz")
    case (true, true):
        print("FizzBuzz")
    default:
        print(i)
    }
}

В приведенном выше коде мы создаем кортеж из двух значений: результат вычисления i % 3 == 0 и результат вычисления i % 5 == 0. Теперь мы можем учитывать различные значения кортежей: (true, false), (false, true), (true, true). Если ни один из этих случаев не совпадает, мы выводим значение i.

Поскольку мы используем switch для проверки значений кортежа, мы также можем проверять различные совпадающие значения в кортеже:

let airplane = (type: "737-800", heading: "LAX")
 
switch airplane {
case ("737-800", _):
    print("Этот самолет модели 737-800.")
case (let type, "LAX"):
    print("Этот \(type) летит в аэропорт Лос-Анджелеса.")
default:
    print("Неизвестный самолет.")
}
 
// Этот самолет модели 737-800.

В приведенном выше коде мы отвечаем 3 разных случая.

Выражение let type называется связыванием значения. Это позволяет нам привязать значение кортежа к константе. Теперь внутри case блока вы можете использовать эту константу, например, распечатать ее.

Использование switch с where

Мы также можем использовать switch с оператором where:

enum Response {
    case error(Int, String)
    case success
}
 
let httpResponse = Response.success
 
switch httpResponse {
case .error(let code, let status) where code > 399:
    print("HTTP Ошибка: \(code) \(status)")
case .error:
    print("HTTP запрос неуспешен")
case .success:
    print("HTTP запрос успешен")
}
 
// HTTP запрос успешен

В приведенном коде происходят две вещи:

  • Мы создаем перечисление Response, которое имеет два случая: .error и .success. Случай .error имеет два соответствующие значения: целое число и строку.
  • Мы оцениваем значение httpResponse с помощью оператора switch, реагируя на разные значения перечисления Response.

Если мы изменим значение httpResponse:

let httpResponse = Response.error(404, "Not Found")
// HTTP Ошибка: 404 Not Found

Или:

let httpResponse = Response.error(301, "Moved Permanently")
// HTTP запрос неуспешен

Есть еще один .error случай, который нас особенно интересует, а именно код ошибки, который больше, чем 399.

Коды состояния HTTP, которые используются в интернете, указывают на то, что коды состояния от 400 и выше являются ошибками клиента и сервера. Иными словами, когда вы получаете один из них, что-то пошло не так.

В приведенном выше коде мы используем привязку значений для констант code и status соответствующих значений перечисления Response. Мы также используем ключевое слово where, чтобы указать, что этот случай должен выполняться для любого значения code, превышающего 399.

Читайте также:
Добавить комментарий

Ваш адрес email не будет опубликован.