Swift
String Comparison
Ignore Case
Programming
Swift Language

How to compare two strings ignoring case in Swift language?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Comparing two strings while ignoring case is easy in Swift, but the best API depends on what kind of text you are matching. Technical identifiers, user-facing search text, and localized display strings can all need slightly different rules.

For many everyday cases, compare(_:options:) with .caseInsensitive is the clearest solution. Beyond that, you may also need to think about diacritics, whitespace normalization, and locale.

The Basic Case-Insensitive Comparison

A direct equality helper can be written like this:

swift
1import Foundation
2
3func equalsIgnoringCase(_ lhs: String, _ rhs: String) -> Bool {
4    lhs.compare(rhs, options: [.caseInsensitive]) == .orderedSame
5}
6
7print(equalsIgnoringCase("Token", "token"))

This is explicit and readable. It also makes it clear that you are asking for a comparison rule, not manually lowercasing strings and hoping that is good enough.

Why Lowercasing Both Sides Is Not Always Ideal

You will often see code like this:

swift
let same = lhs.lowercased() == rhs.lowercased()

That can work for simple cases, but it is not always the best choice. Case mapping can be locale-sensitive, and once comparison logic grows beyond trivial ASCII text, the compare APIs give you more control and make the intent clearer.

If your app deals with user-facing strings in multiple languages, choosing the comparison API deliberately is worth it.

Add Diacritic Handling for Search-Like Behavior

Sometimes users expect "cafe" to match "CAFÉ", not just "Cafe". In those cases, combine case-insensitive and diacritic-insensitive comparison:

swift
1import Foundation
2
3func searchEquals(_ lhs: String, _ rhs: String, locale: Locale) -> Bool {
4    lhs.compare(
5        rhs,
6        options: [.caseInsensitive, .diacriticInsensitive],
7        range: nil,
8        locale: locale
9    ) == .orderedSame
10}
11
12print(searchEquals("CAFÉ", "cafe", locale: Locale(identifier: "fr_FR")))

That is often a better rule for search boxes and user-entered text than pure case insensitivity alone.

Normalize Surrounding Whitespace When Appropriate

Sometimes the real problem is not just casing. It is casing plus accidental spaces:

swift
1import Foundation
2
3func normalizedEquals(_ lhs: String, _ rhs: String) -> Bool {
4    let left = lhs.trimmingCharacters(in: .whitespacesAndNewlines)
5    let right = rhs.trimmingCharacters(in: .whitespacesAndNewlines)
6    return left.compare(right, options: [.caseInsensitive]) == .orderedSame
7}
8
9print(normalizedEquals("  Hello ", "hello"))

Do this only when trimming is part of the business rule. For technical tokens, leading and trailing spaces may signal bad input that should be rejected instead.

Make the Comparison Policy Explicit

If different features need different rules, capture that in one place instead of scattering ad hoc comparisons:

swift
1import Foundation
2
3enum MatchPolicy {
4    case strictCaseInsensitive
5    case userSearch(locale: Locale)
6}
7
8func matches(_ lhs: String, _ rhs: String, policy: MatchPolicy) -> Bool {
9    switch policy {
10    case .strictCaseInsensitive:
11        return lhs.compare(rhs, options: [.caseInsensitive]) == .orderedSame
12    case .userSearch(let locale):
13        return lhs.compare(
14            rhs,
15            options: [.caseInsensitive, .diacriticInsensitive],
16            range: nil,
17            locale: locale
18        ) == .orderedSame
19    }
20}

That keeps identifier comparison separate from user-friendly search semantics.

Common Pitfalls

The biggest mistake is assuming one rule fits every feature. A login token, a sort key, and a search query are not necessarily the same kind of string comparison problem.

Another common issue is lowercasing one side but not the other, or trimming one side but not the other. If you normalize input, do it symmetrically.

Developers also forget locale. For user-facing text, a comparison that looks correct in one language can behave unexpectedly in another if locale-sensitive rules are ignored.

Finally, do not hide important comparison behavior in inline code everywhere. A small helper or policy function makes the rule visible and testable.

Summary

  • In Swift, compare(_:options:) with .caseInsensitive is a strong default for case-insensitive equality.
  • Lowercasing both strings can work, but it is less expressive and less flexible.
  • Add .diacriticInsensitive when user-friendly search behavior should ignore accents as well as case.
  • Normalize whitespace only when that matches the business rule.
  • Keep comparison rules explicit so different app features do not accidentally share the wrong semantics.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.