Regex in SwiftUI

Regex in SwiftUI

A tutorial on Email Validator with NSRegularExpression

·

3 min read

Using regular expressions (regex) can be a powerful tool in SwiftUI for validating user input and manipulating text. In this blog post, we’ll explore how to use regex in SwiftUI.

The code in this post is available here.

To use regex in SwiftUI, you first need to import the Foundation framework, which contains the NSRegularExpression class for working with regex. Here's an example of how to use regex to validate an email address in SwiftUI:

import SwiftUI
import Foundation

struct ContentView: View {
    @State private var email: String = ""
    @State private var isEmailValid: Bool = false

    var body: some View {
        VStack {
            TextField("Enter email", text: $email)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Text("Email is \(isEmailValid ? "valid" : "invalid")")
                .foregroundColor(isEmailValid ? .green : .red)
                .padding()

            Button("Validate email") {
                isEmailValid = isValidEmail(email)
            }
            .padding()
        }
    }

    func isValidEmail(_ email: String) -> Bool {
        let regex = try! NSRegularExpression(pattern: "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$", options: [.caseInsensitive])
        return regex.firstMatch(in: email, options: [], range: NSRange(location: 0, length: email.utf16.count)) != nil
    }
}

In the above code, we define a TextField for entering an email address, and a Text view that displays whether the email is valid or not. When the "Validate email" button is tapped, we call the isValidEmail function, which uses a regex pattern to validate the email address.

Let’s take a closer look at the regex value:

^[A-Z0-9._%+-]+ - The string being checked must start with one or more (+) of characters that’s a letter(A-Z), a number(0-9) or one of the following special characters (. _ % + -).

@ - The string being checked must contain an "at" sign @, following the characters mentioned above.

[A-Z0-9.-]+ The string being checked must contain one or more letters(A-Z), numbers(0-9), a dot(.) or a hyphen(-), following the "at" sign(@).

\\.[A-Z]{2,}$ The string being checked must ends with($) a dot(.) following by at least 2 ({2,})characters of letters([A-Z]).

For a better user experience, we can also replace the Button with a onChange view modifier so that the email will be checked against the regex whenever its value gets changed.

import SwiftUI
import Foundation

struct ContentView: View {
    @State private var email: String = ""
    @State private var isEmailValid: Bool = false

    var body: some View {
        VStack {
            TextField("Enter email", text: $email)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Text("Email is \(isEmailValid ? "valid" : "invalid")")
                .foregroundColor(isEmailValid ? .green : .red)
                .padding()

//            Button("Validate email") {
//                isEmailValid = isValidEmail(email)
//            }
//            .padding()
                .onChange(of: email) { newValue in
                    isEmailValid = isValidEmail(newValue)
                }
        }
    }

    func isValidEmail(_ email: String) -> Bool {
        let regex = try! NSRegularExpression(pattern: "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$", options: [.caseInsensitive])
        return regex.firstMatch(in: email, options: [], range: NSRange(location: 0, length: email.utf16.count)) != nil
    }
}

Here are a few more examples of how to use regex in SwiftUI:

  • Masking a phone number:
    func maskAPhoneNumber(_ phoneNumber: String) -> String {
        let regex = try! NSRegularExpression(pattern: "^\\d{3}\\d{3}\\d{4}$", options: [])
        return regex.stringByReplacingMatches(in: phoneNumber, options: [], range: NSRange(location: 0, length: phoneNumber.utf16.count), withTemplate: "***-***-$3")
    }
  • Extracting hashtags from a string:
    func extractHashtag(_ string: String) -> [String] {
        let regex = try! NSRegularExpression(pattern: "#\\w+", options: [])
        let matches = regex.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
        return matches.map { match in
            (string as NSString).substring(with: match.range)
        }
    }
  • Replacing all instances of a word in a string:
    func replace(_ old: String, with new: String, in string: String) -> String {
        let regex = try! NSRegularExpression(pattern: "\\b\(old)\\b", options: [.caseInsensitive])
        return regex.stringByReplacingMatches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count), withTemplate: new)
    }
  • Validating a password:
    func isValidPassword(_ password: String) -> Bool {
        let regex = try! NSRegularExpression(pattern: "^(?=.*[A-Z])(?=.*\\d)[A-Za-z\\d@$!%*?&]{8,}$", options: [])
        return regex.firstMatch(in: password, options: [], range: NSRange(location: 0, length: password.utf16.count)) != nil
    }

And that’s all of today’s post. I hope it helps and let me know if it is by leaving a comment. Don’t forget to subscribe to my newsletter if you’d like to receive posts like this via email.

I’ll see you in the next post!