Swift
String manipulation
Prefix checking
Suffix checking
Programming tutorial

How to check what a String starts with prefix or ends with suffix in Swift

Master System Design with Codemia

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

Introduction

Checking whether a Swift string starts with a prefix or ends with a suffix is a very common task in validation, file handling, and command parsing. Swift already provides the right tools for this, so the main work is usually choosing the correct comparison rules for case, whitespace, and localization.

Use hasPrefix and hasSuffix for Exact Matches

The standard library gives you hasPrefix(_:) and hasSuffix(_:). These are the direct and readable way to answer simple yes-or-no questions about the start or end of a string.

swift
1let filename = "report.csv"
2let route = "/api/users"
3
4print(filename.hasSuffix(".csv"))   // true
5print(route.hasPrefix("/api/"))     // true
6print(route.hasSuffix("/"))         // false

These methods are case-sensitive. That is usually correct for commands, route prefixes, and other protocol-like values where exact matching matters. It is also more readable than slicing the string manually.

Normalize Before Comparing When Input Is Human Typed

User-entered text often arrives with inconsistent case or extra whitespace. In that situation, normalize first and then perform the prefix or suffix check on the normalized string.

swift
1let rawCommand = "  Delete user  "
2let normalized = rawCommand
3    .trimmingCharacters(in: .whitespacesAndNewlines)
4    .lowercased()
5
6print(normalized.hasPrefix("delete"))   // true
7print(normalized.hasSuffix("user"))     // true

This pattern keeps the intent obvious. It also makes it clear which transformations are allowed before comparison. That matters because lowercasing input may be correct for commands and file extensions, but wrong for passwords or case-sensitive identifiers.

Match Against a Set of Allowed Prefixes or Suffixes

Real code often checks more than one candidate. A good way to do that is to keep the allowed values in an array and ask whether any of them match.

swift
1let imageExtensions = [".png", ".jpg", ".jpeg", ".gif"]
2let candidate = "avatar.JPG".lowercased()
3
4let isImage = imageExtensions.contains { candidate.hasSuffix($0) }
5print(isImage)   // true

This is easier to maintain than a long chain of || conditions. It also scales naturally if the accepted list needs to be shared with tests or configuration code.

Choose the Right Abstraction for Structured Data

A prefix or suffix check is useful, but sometimes it is a shortcut for data that already has structure. A file path, for example, is often better handled with URL rather than by checking the raw string.

swift
1let url = URL(fileURLWithPath: "/tmp/archive.tar.gz")
2let ext = url.pathExtension.lowercased()
3
4print(ext == "gz")   // true

This is not a replacement for hasPrefix and hasSuffix; it is a reminder that string checks should match the kind of data you have. If you are parsing URLs, file names, or commands with separators, use the higher-level API when it makes the code more robust.

Understand Unicode and Localization Boundaries

Swift String is Unicode-correct, so you should avoid manual index arithmetic just to check a prefix or suffix. The built-in methods already handle character boundaries safely. If you need locale-aware matching, switch to range(of:options:range:locale:) with anchored options instead of forcing everything through lowercasing.

swift
1let name = "Résumé"
2let startsWithResume = name.range(
3    of: "res",
4    options: [.anchored, .caseInsensitive, .diacriticInsensitive],
5    range: nil,
6    locale: .current
7) != nil
8
9print(startsWithResume)   // true

That is a more deliberate choice when your comparison needs to reflect how users read text rather than how a protocol token is spelled.

Common Pitfalls

  • Assuming hasPrefix and hasSuffix ignore case when they actually perform exact comparisons.
  • Forgetting to trim user input, which makes leading or trailing spaces break an otherwise correct match.
  • Writing manual substring logic for the first or last few characters instead of using the safer built-in methods.
  • Treating structured data such as URLs or file paths as raw strings when dedicated APIs are more reliable.
  • Lowercasing everything by default, even in places where the original case is semantically important.

Summary

  • Use hasPrefix(_:) and hasSuffix(_:) for direct, exact checks.
  • Normalize case and whitespace only when the input domain allows it.
  • Use arrays and contains for multiple allowed prefixes or suffixes.
  • Prefer higher-level APIs for structured data such as file paths and URLs.
  • Let Swift's built-in string handling do the boundary work instead of slicing manually.

Course illustration
Course illustration

All Rights Reserved.