Regular expressions in Swift: improve your text validations by using the new Regex APIs
Learn the new Regex API and increase your iOS skill set
Manipulating and validating text could be a difficult task if you don’t have a deep understanding of regular expressions.
Prior to Swift 5.7 if we want to perform a simple validation, like an email format, we would end up writing a regular expression and using it together with NSPredicate
. Not a particularly easy code to understand for beginners with regular expressions.
Fortunately, from Swift 5.7 & iOS 16, we have a brand new declarative API and engine that would help us to manipulate and validate text more efficiently.
Regex
We have three ways to create a Regex
- From a simple string, like the old way
try Regex(#"\\w+"#)
- Using a regex literal
let regex = /\\w+/
- Using Regex Builder (we will cover it in the last section)
Match
We have our regex expression created, but how do we validate it? We have three options:
wholeMatch(of:)
It will try to match the entire string with the regular expression passed as a parameter. If the input doesn't match completely, it will fail.firstMatch(of:)
It will try to find the first substring that matches the regular expression passed as a parameter.prefixMatch(of:)
It will succeed if the string starts with the regular expression passed as a parameter.
- We look for the input to match one or more letters at first, followed by a
:
character, follow by one or more digits. If you look at the input, the portion of the text that will match this regex will be the second part (Age:40
). Also, we're using( )
to capture the matching parts of the input. These values will be available on the match result. - As we’re using
firstMatch
, the engine will match the first portion of the string that meets the criteria. In our example, it will beAge:40
. - The match will fail because after the
:
it will find a substring and not a digit. - As the regex created only matches a portion of the input, the function will fail.
Text manipulation
In addition, we do have three functions with which we can modify the entry text.
trimPrefix(_:)
It will remove the elements of the text that match the regular expression.replacing(_:with:subrange:maxReplacements:)
It will return a new string replacing the portion of the text that matches the regular expression with the value given.split(separator:)
It will split the string into a collection using the regex as separator.
Regex Builder
Apple introduced a more semantic and declarative way to create regular expressions. Regex builder is a DSL alternative that we have from iOS 16.
Let’s explore some of the common functionalities that Regex Builder has by looking at an example. Imagine that we want to process a list of entries on our application to create new users, and we want to validate those entries to ensure that every piece of information that we need meets the validations defined. Every entry will correspond to a new user, and it will have the following format:
John Doe|jdoe@gmail.com|05-31-1991|America
- All the fields are separated by a
|
character. - The user’s information will be in order. Name, email, birthdate, and zone.
We can start creating our regular expression using the Regex builder closure: let regex = Regex { ... }
Let’s start with some basic validations.
- The name component needs to have at least one character, followed by a space, and one or more characters again.
- For the email, we will check that the value starts with at least one character, followed by a
@
character, followed by at least one character again, and ends with.com
. - For the date, we want just to validate the format to be
MM-dd-yyyy
(with-
as a separator). - Last, for the zone, we want to check whether is either
America
orEurope
.
As you can see, this is easier to read and understand. If we want to capture the entries to read them one by one, we need to use Capture instruction.
We can go a step further and separate our validations in constants to make the code even more readable.
We can also transform the captured values. Les transform the zone to a custom enum, and the birthdate in order to discard the time portion of the value, we just want to keep the date itself.
I recommend you watch the following WWDC sessions to get an introduction to the new Regex Builder SDL:
After that, you can start playing around with the Regex Builder.