Removing whitespace from the ends
Text from users and files often has extra spaces at the start or end. Swift's way to remove them is trimmingCharacters(in:). It comes from Foundation, so a standalone file needs import Foundation at the top. You tell it which characters to strip by passing a character set, and it removes those characters from both ends of the string until it meets one that isn't in the set.
import Foundation
let text = " hello "
let result = text.trimmingCharacters(in: .whitespaces)
print("[" + result + "]")
print("[" + text + "]")
print(result.count, text.count)
[hello]
[ hello ]
5 9
The last line shows the lengths, 5 for the trimmed string and 9 for the original. The method returns a new string and leaves the original alone, so the result has to be stored or used.
Which characters count
Two common sets are:
.whitespacescovers spaces and tabs, but not line breaks..whitespacesAndNewlinesalso covers line breaks.
The difference shows on a string with a tab at the front and a newline at the back:
import Foundation
let line = "\t hi there \n"
print(line.trimmingCharacters(in: .whitespaces).debugDescription)
print(line.trimmingCharacters(in: .whitespacesAndNewlines).debugDescription)
"hi there \n"
"hi there"
With .whitespaces the tab and leading space are removed, but the trailing space and newline stay, because the newline isn't in the set and stops the trimming at that end. Text read from a file usually ends with a newline, so .whitespacesAndNewlines is the one you often want.
Only the ends
Whitespace in the middle is never touched:
import Foundation
print(" a b ".trimmingCharacters(in: .whitespaces).debugDescription)
print(" ".trimmingCharacters(in: .whitespaces).isEmpty)
"a b"
true
A string made only of whitespace is trimmed down to the empty string, which makes the trimmed isEmpty a handy check for "blank input".
Trimming other characters
The set doesn't have to be whitespace. CharacterSet(charactersIn:) builds a set from the characters of a string, and .punctuationCharacters is a ready-made set:
import Foundation
print("xxhixx".trimmingCharacters(in: CharacterSet(charactersIn: "x")))
print("!!hi?!".trimmingCharacters(in: .punctuationCharacters))
hi
hi
Cleaning input before comparing
Stray spaces make equal-looking strings compare as different. Trim first, then compare:
import Foundation
let typed = " yes "
print(typed == "yes")
print(typed.trimmingCharacters(in: .whitespaces) == "yes")
false
true
The same habit applies before converting text to a number or looking a word up in a collection: clean the value first, so the extra characters don't cause a failed match.
Without Foundation
The standard library has no trimming method, so without Foundation you build one from drop(while:). Dropping from the front, reversing, dropping again and reversing back removes the spaces at both ends:
let text = " hello "
let front = text.drop(while: { $0 == " " })
let trimmed = String(String(front.reversed()).drop(while: { $0 == " " }).reversed())
print("[" + trimmed + "]")
[hello]
That is a lot of code for a small job, which is why the Foundation method is the usual choice.
The exercise
The constant text holds " hello ". Declare result with let as text.trimmingCharacters(in: .whitespaces). The print(result) that follows then shows hello without the surrounding spaces.
let text = " hello "
let result = text.trimmingCharacters(in: .whitespaces)
print(result)
hello
Common mistakes
- Expecting the original to change. The method returns a new string.
- Using
.whitespaceson text with a trailing newline. The newline stays. Use.whitespacesAndNewlines. - Expecting inner spaces to go. Only the two ends are trimmed. To remove spaces everywhere, replace them with an empty string.
- Dropping the leading dot. The sets are written
.whitespacesin this position, and the compiler works out the type from the parameter.
Key takeaways
trimmingCharacters(in:)removes characters of the given set from both ends and returns a new string..whitespacesmeans spaces and tabs..whitespacesAndNewlinesadds line breaks.- It needs Foundation.
