Swift
String Comparison
Case Insensitive
Programming
Swift Language

How to compare two strings ignoring case in Swift language?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Case-insensitive string comparison in Swift is easy to start and easy to oversimplify. The right API depends on whether you want plain equality, locale-aware text comparison, or search-style matching that also ignores accents and surrounding whitespace.

The Straightforward Equality Check

For simple equality, caseInsensitiveCompare is the most direct tool.

swift
1import Foundation
2
3let left = "ReleaseCandidate"
4let right = "releasecandidate"
5
6let same = left.caseInsensitiveCompare(right) == .orderedSame
7print(same)

This is a clear choice when you want a boolean answer and do not need to control locale explicitly.

Why lowercased() Is Not the Best General Rule

A common shortcut is:

swift
let same = left.lowercased() == right.lowercased()

That can work for controlled ASCII-like identifiers, but it is not the most robust general solution for user-facing text. Unicode and locale-specific casing rules can make naive normalization behave differently from a proper comparison API.

The issue is not that lowercased() is always wrong. The issue is that it quietly embeds a normalization policy that may not match the real product requirement.

Use compare When Locale Matters

If the strings are user-visible and language-sensitive, compare with a locale gives you more control.

swift
1import Foundation
2
3let left = "istanbul"
4let right = "İSTANBUL"
5let turkish = Locale(identifier: "tr_TR")
6
7let same = left.compare(
8    right,
9    options: [.caseInsensitive],
10    range: nil,
11    locale: turkish
12) == .orderedSame
13
14print(same)

This matters because some languages have casing rules that are not well represented by a simplistic lowercase-only approach.

Search-Like Matching Often Needs More Than Case Folding

Filtering and search UIs often want looser matching than pure case-insensitive equality. It is common to ignore case, accents, and accidental whitespace at the same time.

swift
1import Foundation
2
3func normalized(_ value: String, locale: Locale) -> String {
4    value
5        .trimmingCharacters(in: .whitespacesAndNewlines)
6        .folding(options: [.caseInsensitive, .diacriticInsensitive], locale: locale)
7}
8
9let a = "Résumé"
10let b = "resume"
11
12let same = normalized(a, locale: Locale(identifier: "en_US")) ==
13           normalized(b, locale: Locale(identifier: "en_US"))
14
15print(same)

This is often the right behavior for search fields, but not necessarily for exact identity checks. The comparison policy should reflect the user experience you want.

Put the Comparison Rule in One Helper

If the app compares strings in many places, create one helper instead of scattering slightly different rules across the codebase.

swift
1import Foundation
2
3struct StringMatcher {
4    static func equalsIgnoringCase(
5        _ lhs: String,
6        _ rhs: String,
7        locale: Locale = .current
8    ) -> Bool {
9        lhs.compare(
10            rhs,
11            options: [.caseInsensitive],
12            range: nil,
13            locale: locale
14        ) == .orderedSame
15    }
16}
17
18print(StringMatcher.equalsIgnoringCase("Hello", "hello"))

Centralizing the rule avoids inconsistent behavior between screens, validation logic, and search code.

Equality and Sorting Should Usually Agree

If the same strings are displayed in sorted lists, the comparison policy used for sorting should usually line up with the one used for equality and filtering.

swift
1import Foundation
2
3let names = ["alice", "Bob", "Álvaro", "charlie"]
4let sorted = names.sorted {
5    $0.compare(
6        $1,
7        options: [.caseInsensitive, .diacriticInsensitive],
8        range: nil,
9        locale: .current
10    ) == .orderedAscending
11}
12
13print(sorted)

Users notice when a list is sorted one way but search and equality checks behave another way.

Common Pitfalls

A common mistake is assuming lowercased() is a universal substitute for real text comparison. It is often fine for internal keys, but it is not the best default for general user-facing strings.

Another issue is forgetting to decide whether accents should matter. Case-insensitive and diacritic-insensitive are separate choices.

Developers also frequently ignore whitespace around user input. That leads to frustrating comparisons where values look equal on screen but fail in code.

Summary

  • Use caseInsensitiveCompare for straightforward case-insensitive equality.
  • Use compare with a locale when language-specific rules matter.
  • Use .folding and trimming when search should ignore accents and whitespace as well.
  • Avoid treating lowercased() as the universal answer for user-facing text.
  • Centralize comparison rules so the app behaves consistently.

Course illustration
Course illustration

All Rights Reserved.