Думаю, каждый из нас сталкивался с задачей валидации данных в приложениях. Например, при регистрации пользователя нужно убедиться что email имеет правильный формат, а пароль удовлетворяет требованиям безопасности и так далее. Можно привести массу примеров, но все в итоге сводится к одной задаче — валидация данных перед отправкой формы. Работая над очередным проектом, я задумался над тем, чтобы создать универсальное решение, а не писать методы валидации для каждого экрана с формой отдельно. В Swift 5.1 появилась аннотация @propertyWrapper, и я подумал, что было бы удобно иметь синтаксис наподобие следующего: Первым делом нужно было определиться с тем, как будут выглядеть и работать валидаторы. В рамках моего проекта мне было необходимо проверить валидность данных и вывести соответствующие сообщения об ошибках. Необходимости в более сложной обработке ошибок не было, поэтому реализация валидатора получилась следующая: Тут все просто. Валидатор содержит сообщение об ошибке, с помощью которого создается ValidationError, если валидация не пройдена. Это упрощает обработку ошибок, поскольку все валидаторы возвращают один и тот же тип ошибки, но с разными сообщениями. В качестве примера можно привести код валидатора, проверяющего строку на соответствие регулярному выражению: Данная реализация содержит одну известную многим проблему. Поскольку протокол Validator содержит associatedtype, то мы не можем создать переменную типа Для решения данной проблемы используем стандартный подход, а именно, создание структуры AnyValidator.
 Думаю, тут нечего комментировать. Это стандартный подход для решения проблемы описанной выше. Также было бы полезно добавить расширение для протокола Validator, позволяющее создавать AnyValidator объект.
 С валидаторами разобрались, можно переходить непосредственно к реализации обертки @Validated. В цели данной статьи не входит разбор того как работают обертки propertyWrapper и какой синтаксис они используют. Если вам еще не удалось с ними познакомиться, то советую прочитать мою другую статью How to Approach Wrappers for Swift Properties(English). Данная реализация позволяет нам объявлять свойства, требующие валидации следующим образом: И получать массив ошибок валидации в любой момент времени следующим образом 
Есть вероятность, что некоторые комбинации валидаторов (например, валидация email) будут встречаться в приложении на нескольких экранах. Для того, чтобы избежать копирования кода, можно в таких случаях создавать отдельный wrapper, унаследованный от Validated. К сожалению, на данный момент аннотация @propertyWrapper обязывает переопределять wrappedValue и projectedValue, в противном случае мы получим ошибку компиляции. Выглядит это как баг реализации, так что возможно, что в будущих версиях Swift это будет исправлено. Вместе с iOS13 пришел нативный фреймворк для реактивного программирования Combine. И я подумал, что может быть полезным иметь следующий синтаксис: Это позволит обновлять информацию об ошибках валидации в режиме реального времени (после каждого введенного символа). Первоначальная реализация этой идеи выглядела следующим образом: Из-за того, что stored property не может быть помечено аннотацией @available, пришлось применить work around со свойствами _subject и subject. В остальном все должно быть предельно понятным. Создается объект PassthroughObject, который отправляет сообщения каждый раз, когда меняется wrappedValue. В результате сообщения об ошибках валидации меняются по мере заполнения пользователем формы.

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