Regular Expressions Tutorial: Getting Started
In this tutorial, you’ll learn how to implement regular expressions in an iOS app using Swift 4.2. By Tom Elliott.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Regular Expressions Tutorial: Getting Started
30 mins
Regular Expression Basics
If you haven’t heard of regular expressions — also called regex — before, it’s probably worth wrapping your head around the basics before continuing with this tutorial. Fortunately, we have you covered! Check out this Introduction to Regular Expressions tutorial here.
Implementing Regex in iOS
Now that you know the basics, it’s time to use regular expressions in an app.
Use the Download Materials button at the top or bottom of this tutorial to download the starter project. Open the iRegex starter project in Xcode and run it.
You’re going to build a diary app for your boss — a Super Villain! Everyone knows that Super Villains need to keep track of all their diabolical plans for world domination, right? There’s lots of planning to do and you, as the minion, are part of these plans — your part being to build the app for the other plans!
The UI for the app is mostly complete, but the core functionality of the app relies on regular expressions, which it doesn’t have… yet!
Your job in this tutorial is to add the required regular expressions into this app to make it shine (and hopefully avoid being thrown into a vat of molten hot magma).
Here are a few sample screen shots demonstrating the final product:
The final app will cover two common use cases with regular expressions:
- Performing text search: highlighting, as well as search and replace.
- Validating user input.
You’ll start by implementing the most straightforward use of regular expressions: text search.
Implementing Search and Replace
Here’s the basic overview of the search-and-replace functionality of the app:
- The Search view controller,
SearchViewController
has a read-onlyUITextView
that contains an excerpt from your boss’ private diary. - The Navigation bar contains a Search button that will present
SearchOptionsViewController
modally. - This will allow your evil boss to type information into the field and tap “Search.”
- The app will then dismiss the Search view and highlight all matches from the diary in the Text view.
- If your boss selected the “Replace” option in
SearchOptionsViewController
, the app will perform a search-and-replace function for all matches in the text, instead of highlighting the results.
NSAttributedString
property of UITextView to highlight the search results.You could also implement the highlighting functionality using Text Kit. Be sure to check out the Text Kit Tutorial in Swift to find out more.
There’s also a Reading Mode button that will allow highlighting all the dates, times and splitters between each entry in the diary. For simplicity’s sake, you won’t cover every possible format of date and time strings that can appear in the text. You’ll implement this highlighting functionality at the very end of the tutorial.
Your first step to getting the search functionality to work is to turn standard strings representing regular expressions into NSRegularExpression
objects.
Open SearchOptionsViewController.swift. SearchViewController
presents this view controller modally and allows the user to enter his or her search (and optional replace) terms, as well as specifying whether the search should be case sensitive or match only whole words.
Take a look at the SearchOptions
struct at the top of the file. SearchOptions
is a simple struct that encapsulates the user’s search options. The code passes an instance of SearchOptions
back to SearchViewController. It would be good to be able to use this directly to construct an appropriate NSRegularExpression
. You can do this by adding a custom initializer to NSRegularExpression
with an extension.
Choose File ▸ New ▸ File… and choose Swift File. Name your file RegexHelpers.swift. Open the new file and add the following code:
extension NSRegularExpression {
convenience init?(options: SearchOptions) throws {
let searchString = options.searchString
let isCaseSensitive = options.matchCase
let isWholeWords = options.wholeWords
let regexOption: NSRegularExpression.Options =
isCaseSensitive ? [] : .caseInsensitive
let pattern = isWholeWords ? "\\b\(searchString)\\b" : searchString
try self.init(pattern: pattern, options: regexOption)
}
}
This code adds a convenience initializer to NSRegularExpression
. It uses the various settings within the passed-in SearchOptions
instance to configure things correctly.
Things to note:
- Whenever the user requests a case-insensitive search, the regular expression uses the
.caseInsensitive
NSRegularExpressionOptions
value. The default behavior ofNSRegularExpression
is to perform case-sensitive searches, but, in this case, you’re using the more user-friendly default of case-insensitive searches. - If the user requests a whole word search, then the app wraps the regular expression pattern in the
\b
character class. Recall that\b
is the word boundary character class, so putting\b
before and after the search pattern will turn it into a whole word search (that is, the pattern “\bcat\b” will match only the word “cat,” but not “catch”).
If, for any reason, it’s not possible to create the NSRegularExpression
, then the initializer will fail and return nil
. Now that you have the NSRegularExpression
object, you can use it for matching text.
Open SearchViewController.swift, find searchForText(_:replaceWith:inTextView:)
, and add the following implementation to the empty method stub:
if let beforeText = textView.text, let searchOptions = self.searchOptions {
let range = NSRange(beforeText.startIndex..., in: beforeText)
if let regex = try? NSRegularExpression(options: searchOptions) {
let afterText = regex?.stringByReplacingMatches(
in: beforeText,
options: [],
range: range,
withTemplate: replacementText
)
textView.text = afterText
}
}
First, this method captures the current text in the UITextView
and calculates the range of the entire string. It’s possible to apply a regular expression to just a part of your text, which is why you need to specify the range. In this case, you’re using the the entire string, which will result in the regular expression being applied to all of your text.
The real magic happens in the call to stringByReplacingMatches(in:options:range:withTemplate:)
. This method returns a new string without mutating the old string. Then the method sets the new string on the UITextView
so that the user can see the results.
Still in SearchViewController, find highlightText(_:inTextView:)
and add the following:
// 1
let attributedText = textView.attributedText.mutableCopy() as! NSMutableAttributedString
// 2
let attributedTextRange = NSMakeRange(0, attributedText.length)
attributedText.removeAttribute(
NSAttributedString.Key.backgroundColor,
range: attributedTextRange)
// 3
if let searchOptions = self.searchOptions,
let regex = try? NSRegularExpression(options: searchOptions) {
let range = NSRange(textView.text.startIndex..., in: textView.text)
if let matches = regex?.matches(in: textView.text, options: [], range: range) {
// 4
for match in matches {
let matchRange = match.range
attributedText.addAttribute(
NSAttributedString.Key.backgroundColor,
value: UIColor.yellow,
range: matchRange
)
}
}
}
// 5
textView.attributedText = (attributedText.copy() as! NSAttributedString)
Here’s a step-by-step explanation of the code above:
- First, get a mutable copy of the textview’s
attributedText
. - Then, create an
NSRange
for the entire length of the text and remove any background color text attributes that already exist within it. - As with find and replace, create a regular expression using your convenience initializer and fetch an array of all matches for the regular expression within the textview’s text.
- Loop through each match and add a yellow color background attribute for each one.
- Finally, update the
UITextView
with the highlighted results.
Build and run your app. Try searching for various words and groups of words! You’ll see the search terms highlighted throughout your text, as shown in the image below:
Try searching for the word “the” using various options and see the effects. Notice, for example, that, when using whole words, the ‘the’ in ‘then’ does not highlight.
Also, test out the search-and-replace functionality to see that your text strings are replaced as expected. Also try both the ‘match case’ and ‘whole words’ options.
Highlighting and replacing text are both great. But how else can you effectively use regular expressions in your apps?