Нужно определить результат выполнения кода: какое условие проверяет if case, не анализируя содержимое связанного значения?
import Foundation
enum LoadState {
case loading
case loaded([Int])
case failed(String)
}
let state = LoadState.failed("таймаут")
if case .failed = state {
print("ошибка")
} else {
print("успех")
}
Программа напечатает ошибка. Запись if case .failed = state проверяет, что значение перечисления имеет вариант failed, не извлекая и не сравнивая его связанное значение String.
Это сопоставление с образцом, а не сравнение двух значений перечисления. Поэтому условие будет истинным для любого LoadState.failed(...), независимо от текста ошибки.
Перечисления со связанными значениями позволяют представить состояние как одно из взаимоисключающих событий, при этом каждый вариант может хранить собственные данные. Например, состояние загрузки может быть loading, loaded с результатом или failed с причиной ошибки.
Сопоставление с образцом появилось как средство безопасной работы с такими вариантами без ручных проверок типа, приведения и отдельных флагов. Оно делает структуру данных явной и помогает компилятору контролировать обработку вариантов перечисления.
Проверка только факта ошибки часто нужна отдельно от анализа её причины. Если для этого сравнивать строки ошибок или вводить дополнительное булево свойство, логика становится хрупкой: появится риск рассинхронизации состояния и причины.
В коде состояние содержит связанное значение String, но текущая задача — определить только вариант перечисления. Неверное понимание if case может привести к попытке сравнивать весь экземпляр перечисления или извлекать значение, которое фактически не требуется.
В выражении if case .failed = state левая часть задаёт образец варианта failed, а правая — значение, с которым выполняется сопоставление. Если state имеет вид .failed(...), условие истинно; содержимое скобок при этом игнорируется.
Связанное значение можно извлечь явно:
Здесь message получает строку таймаут. Важно, что if case не проверяет равенство связанных данных и не требует, чтобы перечисление соответствовало Equatable.
Если нужно обработать все варианты, обычно применяют switch:
switch должен покрывать все варианты либо содержать default. if case удобен, когда интересует один образец, а остальные значения можно обработать единым путём.
К образцу можно добавить условие where, например if case let .failed(message) = state, message.isEmpty. Тогда сначала проверяется вариант failed и извлекается значение, после чего дополнительно проверяется условие.
Клиент сетевого слоя получает состояние запроса. Для показа общего сообщения об ошибке интерфейсу достаточно определить вариант failed, но для журналирования требуется сохранить конкретный текст.
Можно использовать отдельный флаг hasError, однако он дублирует информацию, уже представленную перечислением. Такой подход допускает некорректные состояния вроде hasError == false при наличии ошибки.
Можно сравнивать строку ошибки с известными значениями, но это связывает код интерфейса с текстами и не решает задачу проверки самого варианта. Более того, разные ошибки могут иметь разные сообщения.
Предпочтительно использовать if case .failed = state для общего поведения, а if case let .failed(message) = state — там, где требуется причина. В результате модель остаётся единственным источником состояния, а код явно показывает, извлекаются ли связанные данные.
if case .failed("таймаут") = state и что именно тогда проверяется?Да, такой образец проверяет не только вариант failed, но и совпадение связанного строкового значения с "таймаут". Это уже более узкое условие: значение .failed("соединение закрыто") не совпадёт.
Такой синтаксис полезен для конкретного известного значения, но обычно не подходит для бизнес-логики, если текст сообщения может меняться или локализоваться. Для общей проверки варианта следует игнорировать payload, а для содержательного анализа — извлечь его и проверить отдельным условием.
if case let .failed(message) = state от обычного switch?if case проверяет один образец и выполняет ветку при совпадении. Другие варианты не обязаны быть перечислены, поэтому конструкция удобна для локального условия.
switch предназначен для разветвления по нескольким вариантам и проверяется компилятором на полноту. Если варианты перечисления изменятся, неполный switch может потребовать явного обновления, тогда как if case продолжит проверять только интересующий вариант.
if?Можно объединить сопоставление с образцом и условие через where:
Сначала Swift проверяет, что значение имеет вариант failure, и извлекает код. Затем вычисляется обычное булево условие code >= 500. Символ _ явно показывает, что сообщение извлекать не требуется.