HCN DEV

한국어로 보기

Working with Swift Strings

Working with Swift Strings feature image

Forms of Swift Strings

In this post, we’ll explore Swift’s String and its various forms. In Swift, you can represent a string like this:

let str = "hello"

In previous versions of Swift (Swift 3), you could only define single-line strings. However, in Swift 4, you can create multi-line strings using triple quotes (""").

let multiLine = """
The White Rabbit put on his spectacles, "Where shall I begin, please begin your Majesty?" he asked.

"Begin at the beginning,"

    Indentation is included.
        Another indent
"""

print(multiLine)

/* Output:
The White Rabbit put on his spectacles, "Where shall I begin, please begin your Majesty?" he asked.

"Begin at the beginning,"

    Indentation is included.
        Another indent
*/

Leading white space in multi-line strings is omitted when printing. However, if indentation occurs after the starting sentence, it will be included.

Extended Grapheme Clusters

In Swift, one character represents a “Single Extended Grapheme Cluster.” Extended Grapheme Clusters represent human-readable characters, and this concept applies not only to English but also to other languages. For example, consider Korean characters:

let precomposed: Character = "\u{D55C}"                  // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"   // ᄒ, ᅡ, ᆫ
// Both represent the Character "한."

Surprisingly, decomposed consists of three scalars. In Extended Grapheme Clusters, it’s not a one-to-one mapping where one Character equals one scalar. This is why it’s challenging to access strings by index. Each Character can consist of one or more scalars, making it challenging to allocate consistent memory sizes per Character, which makes index-based access impossible.

Note: Extended Grapheme Clusters in Swift allow intuitive representation of various languages, but their variable sizes make direct index-based access to a String impossible.

Accessing Swift Strings

In Swift, accessing individual characters using String[Int] is challenging. Instead, Swift provides methods for such access. Two essential methods are startIndex and endIndex.

Accessing Individual Characters (startIndex, endIndex)

let str = "Hello"

print(str.startIndex) // Index(_base: Swift.String.UnicodeScalarView.Index(_position: 0), _countUTF16: 1)
print(str.endIndex) // Index(_base: Swift.String.UnicodeScalarView.Index(_position: 5), _countUTF16: 0)

In the above example, str.startIndex returns 0, and str.endIndex returns 5. Be cautious, as endIndex is 5, not 4. While “Hello” has five characters, indexing starts from 0 and goes up to 4, but endIndex is 5, indicating the length of the entire string. Thus, str[str.endIndex] results in an error. To access the last character, you need to use an index before endIndex.

Swift provides methods like str.index(before:) and str.index(after:) for accessing characters before and after endIndex. To access the last character, you can use str.index(before: str.endIndex).

Accessing Individual Characters (offsetBy)

To access characters in the middle of a string, you can use the index(_:offsetBy:) method.

Note: The offsetBy method returns a position by adding a given integer value to the starting position.

let str = "Hello World"

print(str[str.index(str.startIndex, offsetBy: 0)]) // H
print(str[str.index(str.startIndex, offsetBy: 6)]) // W

print(str[str.index(str.endIndex, offsetBy: -1)]) // d
print(str[str.index(str.endIndex, offsetBy: -3)]) // r

In the examples above, the first two print statements access characters at specific offsets from the startIndex. The last two statements access characters from the endIndex. Negative values indicate positions counting from the end.

Accessing the Entire String with Loops

You can also access a string using loops in three ways. The first way accesses individual characters using str.

let str = "Hello"

for char in str {
  print(char) // H e l l o (each character)
}

The second way accesses indices using indices.

for index in str.indices {
  // Accesses indices generated by Swift, not integers.
  print(index) // Index(_base: Swift.String.UnicodeScalarView.Index(_position: 0), _countUTF16: 1)...
}

The last way accesses both indices and individual characters simultaneously.

for (index, value) in str.enumerated() {
    // index is an integer.
    print("index: \(index), value : \(value)")  // index: 0, value: H
}

Swift String Insert and Remove

Swift’s String insertion specifies what content to insert and where to insert it. The methods for this purpose are insert(_:at:) and insert(contentsOf:at:).

let str = "Hello"

str.insert("A", at: str.startIndex) // Result: AHello
str.insert(contentsOf: " World", at: str.endIndex) // Result: AHello World

For inserting individual characters, you don’t need to use contentsOf.

String removal is similar to insertion but specifies where and what to remove. The methods are remove(_:at:) and removeSubrange(_:).

let str = "AHello World"

str.remove(at: str.startIndex) // Result: Hello World

let rangeOfWorld = str.index(str.endIndex, offsetBy: -6)..<str.endIndex
str.removeSubrange(rangeOfWorld) // Result: Hello

Be cautious when using `remove(_:at:)

` with ranges. Ranges must be specified using String.index or str.endIndex.

Prefix and Suffix

The hasPrefix(_:) and hasSuffix(_:) methods check if a string starts with or ends with a specific substring, respectively.

var s = "한글"

if s[s.startIndex] == "한" {
    print("The first character is '한'.")
}
if s.hasPrefix("한") {
    print("The first character is '한'.")
}

if s.hasSuffix("한글") {
    print("The last characters are '한글'.")
}

Substring

Substring represents a part of a string.

let str = "Hello World"
let range = str[str.startIndex...str.index(str.startIndex, offsetBy: 4)]
let subStr = str[range]

The subStr in this example refers to a part of the original string without allocating new memory. This memory reuse reduces memory allocation costs. However, this approach is not suitable for long-term storage of strings. For long-term storage, it’s better to create a new string.

References

  • Apple Inc. The Swift Programming Language (Swift 4 Beta)