В Swift 2.0 мы встретили паттерн «ловушка». Он заменил множество inout параметров NSError во многих фреймворках и API, но как его использовать?
Протокол ErrorType
Перво-наперво! Что это за ErrorType? Взглянем на Apple Docs…
Как мы видим, это просто пустой протокол и пустое расширение ... Хорошо, давайте посмотрим на Реализацию ErrorType в репозитории Swift на Github:
Помните нашего старого друга NSError?
Становится ясно, как NSError выполняет это определение: у него есть эти свойства, поддерживаемые ivars, к которым 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 с некоторыми примерами кода, показанными в этом посте. Надеюсь, вам понравилось, и предложения приветствуются!