How to Check if a String Contains a Substring in Swift? Complete Guide
\n\nHello, fellow developer! If you've ever written code in Swift and wondered: "How do I find one word inside another?", you've come to the right place. This topic is one of the most popular questions on Stack Overflow (the English version has hundreds of thousands of views). And it's no coincidence: working with strings is a fundamental skill that no application can do without.
\n\nIn this article, we'll cover all the legitimate ways to check if a string contains a substring. From the simplest contains() to advanced techniques with case-insensitive search and regular expressions. Let's go!
1. The Simplest Way: The contains() Method
\n\nSince Swift 1.0, we have had a built-in contains() method on the String type. It works intuitively and is very fast.
let fullString = "Hello, Swift world!"\nlet searchString = "Swift"\n\nif fullString.contains(searchString) {\n print("Yes, the string contains '\\(searchString)'")\n} else {\n print("No, it does not contain it")\n}\n// Output: Yes, the string contains 'Swift'\n\nImportant: the contains() method is case-sensitive. That is, "swift" will not be found in the string "Swift". But we'll fix that a bit later.
2. Case-Insensitive Search: localizedCaseInsensitiveContains()
\n\nOften you need to find a word without paying attention to capital letters. There is a special method for this that works with the user's locale.
\n\nlet text = "Welcome to Swift"\nlet search = "swift"\n\nif text.localizedCaseInsensitiveContains(search) {\n print("Found! Case is no obstacle.")\n} else {\n print("Not found")\n}\n// Output: Found! Case is no obstacle.\n\nThis method uses the current device locale, which is especially important for languages with special comparison rules (e.g., Turkish, where 'i' and 'I' are different letters).
\n\n3. Locale-Aware Search: localizedStandardContains()
\n\nAnother useful method is localizedStandardContains(). It performs a search the way standard iOS search does (e.g., in Spotlight or Finder).
let fileName = "Vacation_Photos_2024.jpg"\nlet query = "Vacation"\n\nif fileName.localizedStandardContains(query) {\n print("File found!")\n}\n// Output: File found!\n\nThis method automatically normalizes strings, removes diacritical marks (e.g., 'é' = 'e'), and works case-insensitively. Perfect for search strings in the user interface.
\n\n4. The Classic Way: range(of:)
\n\nSometimes you need not just to know if a substring exists, but also to get its position. That's where range(of:) comes in. It returns an optional range (Range<String.Index>?).
let phrase = "Learning Swift at pythonlib.ru"\nlet word = "Swift"\n\nif let range = phrase.range(of: word) {\n print("Substring found at position: \\(range.lowerBound)")\n // You can even extract a piece of the string\n let extracted = phrase[range]\n print("Extracted: \\(extracted)")\n} else {\n print("Substring not found")\n}\n\nFor case-insensitive search with range, use the .caseInsensitive option:
if let range = phrase.range(of: "swift", options: .caseInsensitive) {\n print("Found case-insensitively: \\(phrase[range])")\n}\n\n5. Checking the Beginning and End of a String
\n\nSometimes you need to check not "does it contain at all", but "does it start with..." or "does it end with...". There are special methods for this:
\n\nlet url = "https://pythonlib.ru"\n\nif url.hasPrefix("https://") {\n print("This is a secure URL")\n}\n\nif url.hasSuffix(".ru") {\n print("Russian domain")\n}\n\nBoth methods are also case-sensitive.