Values and types

Strings in Swift

Learn how to work with strings in Swift, including string literals, multi-line strings, interpolation, and concatenation, with beginner-friendly examples.

This tutorial belongs to the Swift series

Strings are everywhere in programming: names, messages, file paths, everything a user reads on screen.

In Swift you create a string with the string literal syntax, using double quotes:

let name = "Roger"

Single quotes are not valid string delimiters. 'Roger' doesn’t compile.

Multi-line strings

A string can span multiple lines if you wrap it in three double quotes:

let description = """
    a long
    long
    long description
    """

The indentation of the closing """ decides how much leading whitespace Swift strips from each line. Here every line loses 4 spaces.

Interpolation

To put a value inside a string, use string interpolation: \(...) with an expression inside the parentheses:

let age = 8

let name = """
    Roger, age \(age)
    Next year he will be \(age + 1)
    """

The result is Roger, age 8 on the first line and Next year he will be 9 on the second. Any expression works inside the parentheses, not just a variable name.

Concatenation

Join two strings with +:

var name = "Roger"
name = name + " The Dog"

Or append with +=:

var name = "Roger"
name += " The Dog"

Or use the append(_:) method:

var name = "Roger"
name.append(" The Dog")

All three leave name equal to "Roger The Dog". Notice name is a var. You can’t append to a let string.

Useful properties and methods

count gives you the number of characters:

let name = "Roger"
name.count // 5

Every string comes with a long list of methods. The ones I use most:

  • removeFirst() removes the first character
  • removeLast() removes the last character
  • lowercased() returns a new lowercase string
  • uppercased() returns a new uppercase string
  • starts(with:) returns true if the string starts with a given substring
  • contains() returns true if the string contains a given character

Indexes and substrings

Here’s the part that surprises people coming from other languages. Strings in Swift are Unicode, and a single character can take a variable amount of memory. So you can’t write name[1] to get the second letter. You have to work with indexes.

Every string gives you its first index through startIndex:

let name = "Roger"
name.startIndex

This is not the number 0. It’s a String.Index value, a position inside that specific string.

To reach a specific position, use index(_:offsetBy:):

let name = "Roger"
let i = name.index(name.startIndex, offsetBy: 2)
name[i] // "g"

The same index gives you a substring:

let name = "Roger"
let i = name.index(name.startIndex, offsetBy: 2)
name.suffix(from: i) // "ger"

// or with the subscript:
name[i...] // "ger"

Be careful: the result is a Substring, not a String:

let name = "Roger"
let i = name.index(name.startIndex, offsetBy: 2)
print(type(of: name.suffix(from: i)))
// Substring

A substring shares memory with the original string instead of copying it, which makes slicing cheap. When you need to keep the result around for a long time, convert it with String(name[i...]) so the original string can be released.

Strings are collections, so you can loop over their characters with for-in. We’ll see that in the loops lessons.

Lesson completed