Working with Strings in Swift
Learn how to use Swift's String type and its companions Character, Index and Substring.
05 Jun 2021 路 5 min read
Representing text values, Strings are one of the most common data structures we use when coding. In this post, we will learn how to work with Swift's String type and its companions Character, Index and Substring.
Let's directly jump into an example.
var fruit = "apple" // fruit is of type Stringfruit.isEmpty // returns falsefruit.count // returns 5fruit.uppercased() // returns "APPLE"fruit.first // returns the first Character - afruit.last // return the last Character - efruit.append("!") // changes "apple" to "apple!"
Above, we can see some of the String properties and methods in action that are mostly self-explanatory.
Under the hood, Swift's String type is modeled as a collection of characters represented by the Character type. Strings behave like other collections in many aspects. For example, we can iterate over their characters just like how we would iterate over an array:
for character in "hello 馃悓" {print(character) // prints "h", "e", "l", "l", "o", "馃悓"}

Every Character type represents a human-readable character which can consist of one or more Unicode characters. Unicode is an international standard for encoding, representing and processing text. It enables us to represent almost any character from any language in a standardised form.
let emoji: String = "馃悓"emoji.count // returns 1emoji.utf8.count // returns 4
As we can see above, the number of Swift characters and the actual number of UTF-8 characters aren鈥檛 always equal.
String interpolation
String interpolation provides a way to construct a new String from a mix of constants or variables. Each variable we insert into the string literal has to be wrapped in a pair of parentheses, prefixed by a backslash.
let age = 10let description = "\(age) years old"print(description) // prints "10 years old"
Swift' String interpolation is able to handle a variety of different data types automatically.
String indices & substrings
To access certain parts of a string or to modify it, Swift provides the Swift.Index type which represents the position of each Character in a String.
Each string comes with a startIndex and an endIndex. Using those we can derive any other index like this:
let hello = "hello world"let index = hello.index(hello.startIndex, offsetBy: 6) // index with an offset of 6 charactershello[index] // returns Character whello.prefix(upTo: index) // returns Substring "hello "
The above prefix(upTo:) method returns a Substring and not a String. Why? Strings are value types e.g. they get copied every time we pass or reassign them. This has the advantage that no one else is going to change it without our knowledge, but an efficiency disadvantage.
The Substring type is a more efficient string type that enables us to retrieve and pass substrings around without copying. Substrings are meant for short-term usage.
Conclusion
Swift provides a modern powerful API when working with Strings. Some parts however, for example the indices may seem complicated to use.
To simplify the indices usage, we could create some extensions to abstract away the implementation details. For example, the prefix method extension could look like this:
extension String {func prefix(upTo: Int) -> String {let toIndex = self.index(startIndex, offsetBy: upTo)return String(self[..<toIndex])}}
The extension allows us to directly use the Int type instead of the Index type. Instead of creating an index, we can now pass in an integer hello.prefix(upTo: 5) to get a certain prefix of a string.

Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips