В Swift 2.0 мы встретили паттерн «ловушка». Он заменил множество inout параметров NSError во многих фреймворках и API, но как его использовать?

Протокол ErrorType

Перво-наперво! Что это за ErrorType? Взглянем на Apple Docs

Как мы видим, это просто пустой протокол и пустое расширение ... Хорошо, давайте посмотрим на Реализацию ErrorType в репозитории Swift на Github:

Помните нашего старого друга NSError?

Становится ясно, как NSError выполняет это определение: у него есть эти свойства, поддерживаемые ivars, к которым Swift может получить доступ без динамической отправки.

Тестирование ErrorType Swift: исследование

Когда вы используете «throws», Swift ожидает, что вы выдадите ErrorType. Зная, что Swift позволяет создавать не только классы, соответствующие протоколам, но также структуры и перечисления, мы собираемся использовать перечисление, соответствующее ErrorType, для перечисления наших ошибок (и поскольку Apple рекомендует использовать перечисление: P).

Время писать код

Теперь, когда вы знаете, как работает ErrorType и как Apple рекомендует его использовать, давайте посмотрим на код. Мы собираемся создать код для деления 2 чисел и обработки, если какое-либо из них равно 0, чтобы предотвратить ошибку деления.

Вот наше перечисление, соответствующее протоколу ErrorType:

Теперь наша функция деления:

А затем наша функция вычисления:

С помощью этого кода мы уже используем наши пользовательские ошибки и обрабатываем их. Мы не сказали, что пункт о перехвате должен быть исчерпывающим, это означает, что все возможные значения должны быть «отловлены». По этому поводу есть обсуждения в списке рассылки по быстрой эволюции и некоторые документы в репозитории Swift на Github. Рекомендуемое чтение !!!

Но подождите, нам что-то здесь не совсем нравится ... знаете, что это?

Да, мы не совсем его пропагандируем - по крайней мере, как следует. Согласно теории распространения (которую я только что придумал и следую 😝) мы должны:

1. Выдвигайте ошибку до тех пор, пока ответственный за ее обработку не обработает, в этом случае специально покажите сообщение пользователю.

2. Отправьте конфиденциальную информацию, такую ​​как код ошибки, который можно было получить только там, где ошибка была изначально выдана.

Итак, давайте внесем здесь некоторые изменения. Во-первых, измените наш DivisionErrorEnum на код (Int), чтобы увидеть, о чем мы здесь говорим.

А теперь изменим наше предложение catch:

Теперь вы можете видеть, что мы распространяем ошибку на функцию «вычислить», а не отправляем заранее определенное сообщение. На этом простом примере мы видим, что уже решили проблему наличия разных сообщений для одной и той же ошибки в разных частях нашей системы.

Включение / отключение распространения ошибки

Вы должны знать кое-что интересное, что вы можете использовать try? и попробовать!. Как заявляет Apple:

Вы пробуете? для обработки ошибки путем преобразования ее в необязательное значение. Если при оценке попытки выдается ошибка? выражение, значение выражения равно нулю.

В приведенном ниже примере оба кода имеют одинаковое поведение:

И вы можете использовать "попробуй!" а также отключить распространение ошибки. В приведенном ниже примере мы УВЕРЕНЫ, что наш код не выдаст ошибку, поскольку x и y отличны от 0.

Но если у вас есть значения x и y, поступающие из пользовательского ввода, и он допускает ноль, мы обязательно должны попробовать? или создайте наше заявление о ловле рыбы.

Другой пример, предоставленный Apple:

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

ВНИМАНИЕ !!! Точно так же, как и с необязательными переменными, будьте мудры, используя «попробуйте!». Если div (2, 2) выдает непредвиденную ошибку, вы получите ошибку времени выполнения - и нам это не нравится.

Здесь у меня есть проект iOS с некоторыми примерами кода, показанными в этом посте. Надеюсь, вам понравилось, и предложения приветствуются!