A Data Validation Solution Utilizing Swift Property Wrappers and SwiftUI View Extensions | by Jonathan Storey | May, 2022

Knowledge validation in Swift and SwiftUI

For higher or worse, the Swift programming language doesn’t present a unified strategy to validation. In consequence, every developer should develop their very own strategy. On this article, I share my hard-won resolution to information validation.

“To err is human, to validate devine.” — (not) Alexander Pope

At a primary degree, validation requires detecting and speaking invalid information. Ideally, validation logic ought to be reusable and permit for incorporation at a number of ranges of the codebase: throughout the mannequin, view, and/or wherever in between. I current a validation bundle that accomplishes all of these objectives in addition to the power to right and format user-entered information. The inspiration of this strategy is a rule-based system. With that system in place, we will leverage the ability of Swift property wrappers and SwiftUI view extensions to use our validation schema throughout the codebase.

Let’s start with the creation of a comparatively easy Swift protocol. Right here’s the code:

Base protocol defining a validation rule

The validation logic will reside with the validate operate, which accepts a price sort and returns a Consequence sort. Underneath the hood, a consequence sort is an enum with two potential outcomes (or instances): success and failure. Importantly, these two instances even have related values that enable us to cross on particulars about our validation final result.

Throughout the protocol, there’s a single property that defines a fallback worth. In our rule, this worth can be utilized as an preliminary worth and will also be used to switch invalid information. The fallback worth can be particularly essential in permitting us to create a well-functioning property wrapper (see beneath), the place we’re in a position to present default values for our fallback worth with extensions.

Extending the validation rule and offering default fallback values

Earlier than we will start making a validation rule, we first must outline an error sort that we are going to use to fulfill the related Failure sort inside our protocol. Any error sort will do. For this instance, we are going to create a string alias known as ErrorMessage in two traces of code:

A fast and simple strategy to create a versatile Error sort by extending and aliasing a String

Utilizing our new Rule protocol and error sort, let’s create a easy rule that we will then use to validate a string. Right here’s the code:

Easy validation rule specifying that the phrase be 12 characters or much less

We will make the identical rule customizable by including a further initializer and variable to the rule. On this case, we are going to enable modification of the rule in order that we will outline the utmost size of our phrase, as you may see beneath:

Making a dynamic validation rule

We will additionally add extra validation logic as wanted. By including one other guard assertion inside our validate operate, we will examine to ensure that all the entered characters are letters, which is proven beneath:

Including extra validation situations to the validation rule

Up up to now, we have now returned completely different error sorts utilizing the .failure case of our validation consequence. Additionally it is attainable to alter the return worth for successes as nicely. In essence, we will use this potential to make our rule auto-correcting or so as to add formatting. Within the following instance, we are going to trim any whitespace earlier than and after the phrase. We’ll then return the trimmed worth inside our validation consequence, which you’ll see beneath:

It’s normally preferable to make any transformations earlier than validating

Now that we have now lastly created a rule, we will use it as a stand-alone validating object, proven right here:

Utilizing a validation rule as a stand-along validator

The above examples are slightly easy and simple however exhibit the power to make use of customized initializers, embody complicated logic, and rework values. Use instances for combining validation and formatting would come with telephone numbers, postal codes, and so forth. Good validation guidelines usually change into fairly concerned in my fingers as I attempt to foresee as many edge instances as attainable.

Good validation is tough work!

The true energy of our validation rule turns into clear as we discover other ways to make use of our validation logic all through the codebase. A primary place to carry out validation utilizing a customized Swift property wrapper is on the property degree. Allow us to soar straight into the code:

Primary property wrapper for validation

The above property wrapper efficiently “wraps” our validation rule and the worth we need to validate. Unsurprisingly, the principle initializer requires each a validation rule and worth. We will even embody different initializers for our property wrapper to permit clean integration in our initiatives. In these initializers, we’re offering default values for our rule and our price, which is proven beneath:

Alternate property wrapper intializers enable us to populate or wrapper with default properties

With a semi-complete property wrapper, we will now incorporate property validation immediately inside our mannequin or ViewModel. With the a number of property wrapper initializers we outlined above, we have now a number of syntactic choices for wrapping our property.

Nevertheless, our property wrapper is incomplete as we can not simply entry the validation consequence. Right here is the place we make the most of a projected worth. In Swift UI state administration, most of the projected values are Bindings. However in a customized property wrapper, we will set the projected worth to no matter we like. On this case, we are going to return our validation consequence utilizing a computed property, as you may see:

A projected worth permits entry of the validation consequence simply inside our code

Now that we have now outlined a projected worth, we will entry our validation consequence at any time utilizing the $ image.

The greenback signal syntax returns our validation consequence as both .success or .failure

Regardless of all of our exhausting work above, the wrapped property stays extra restricted than the unique “unwrapped” property in some essential points. Particularly, whereas a String is Encodable and Decodable (aka Codable), our new wrapped property will not be. This may be remedied by extending our property wrapper to incorporate conformance to these protocols (or every other). Right here is how we add protocol conformance to our property wrapper by way of an extension:

Including conformance to Encodable; solely legitimate property values are encoded
Including conformance to Decodable

Including Encodable conformance is greater than only a comfort. Discover that within the encode operate solely legitimate values are encoded. If a price is invalid, it’s not encoded. As an alternative, the fallback worth is used as a substitute. This ensures that an invalid worth won’t ever be handed within encoded information!

At this level, we will now immediately validate information utilizing our rule object. We will additionally use a property wrapper to include our validation immediately throughout the mannequin (or the view mannequin). However what if we need to incorporate validation inside a SwiftUI view? A view extension is nicely fitted to this process, as you’ll see beneath:

View extension utilizing the validation rule

Some essential issues are taking place above. Discover that the escaping validation operate is fired when the sure worth modifications. This returns a validation consequence by way of closure which might then be used throughout the view. Through the use of a closure, we will deal with the validation consequence as we please and reply accordingly with UI modifications.

When the sector is submitted, we once more examine to ensure that the validated worth matches the sure worth when applicable. If a price underwent transformation (similar to trimming whitespace), it should replace the sure worth on submission.

Here’s what our new view extension would appear like in a correct view:

Validating inside a View utilizing the view extension

With our new view extension, the UI can react instantly to invalid information entry. Attainable UI modifications embody displaying an error message in textual content, altering the textual content shade, or displaying an error icon. In different situations, it might be preferable to forestall saving or to droop navigation till the errors are efficiently resolved. The chances are countless.

And eventually, that is what our validated view appears like in motion:

I hope you discovered this tutorial helpful and that it prompts you to suppose extra about using validation in your initiatives. If you happen to loved the article, please subscribe to encourage me to write down extra.

Glad coding!

A packaged model of this code could be discovered at GitHub. Please be at liberty to make use of it in your initiatives.

More Posts