In this post, we’ll discuss how to check if a String contain another String. We’ll then create an extension that allows for easier case-insensitive checks.

The basics

Checking if a string contains another string is easy, using contains:

let string = "This string contains text"
string.contains("contains") // => true

However, this will not perform a case-insensitive check, which means that

string.contains("Contains") // => false

To allow for case-insensitive contains checks, you could lower-case both strings:

string.lowercased().contains("Contains".lowercased()) // => true

However, this is not that performant, since you create two new strings to perform this check. You could use range instead, and provide it with a .caseInsensitive option:

string.range(of: "Contains", options: .caseInsensitive) != nil // => true

However, I don’t think that this is that readable. We can do better.

Extending String

I think a more readable approach is to create a contains extension with a caseSensitive argument and adjust its logic depending on if the check should be case-sensitive or not:

public extension String {
    
    func contains(_ string: String, caseSensitive: Bool) -> Bool {
        caseSensitive
            ? contains(string)
            : range(of: string, options: .caseInsensitive) != nil
    }
}

We can now perform case-sensitive and case-insensitive contains checks the same way:

string.contains("contains") // => true
string.contains("Contains") // => false
string.contains("Contains", caseSensitive: true) // => false
string.contains("Contains", caseSensitive: false) // => true

I think that this is a lot cleaner, and for case-sensitive checks a lot more readable.

Source code

I have added this extension to my SwiftKit library. You can find the source code here and the unit tests here.