Strings and Characters
String & Character Literals
Section titled “String & Character Literals”String literals in Swift are delimited with double quotes ("):
let greeting = "Hello!" // greeting's type is StringCharacters can be initialized from string literals, as long as the literal contains only one grapheme cluster:
let chr: Character = "H" // validlet chr2: Character = "😊" // validlet chr3: Character = "abc" // invalid - multiple grapheme clustersString Interpolation
Section titled “String Interpolation”String interpolation allows injecting an expression directly into a string literal. This can be done with all types of values, including strings, integers, floating point numbers and more.
The syntax is a backslash followed by parentheses wrapping the value: \(value). Any valid expression may appear in the parentheses, including function calls.
let number = 5let interpolatedNumber = "\(number)" // string is "5"let fortyTwo = "\(6 * 7)" // string is "42"
let example = "This post has \(number) view\(number == 1 ? "" : "s")"// It will output "This post has 5 views" for the above example.// If the variable number had the value 1, it would output "This post has 1 view" instead.For custom types, the default behavior of string interpolation is that "\(myobj)" is equivalent to String(myobj), the same representation used by print(myobj). You can customize this behavior by implementing the CustomStringConvertible protocol for your type.
For Swift 3, in accordance with SE-0089, String.init<T>(_:) has been renamed to String.init<T>(describing:).
The string interpolation "\(myobj)" will prefer the new String.init<T: LosslessStringConvertible>(_:) initializer, but will fall back to init<T>(describing:) if the value is not LosslessStringConvertible.
Special Characters
Section titled “Special Characters”Certain characters require a special escape sequence to use them in string literals:
|Character|Meaning
|---|---|---|---|---|---|---|---|---|---
|\0|the null character
|\\|a plain backslash, \
|\t|a tab character
|\v|a vertical tab
|\r|a carriage return
|\n|a line feed (“newline”)
|\"|a double quote, "
|\'|a single quote, '
|\u{n}|the Unicode code point n (in hexadecimal)
Example:
let message = "Then he said, \"I \u{1F496} you!\""
print(message) // Then he said, "I 💖 you!"Concatenate strings
Section titled “Concatenate strings”Concatenate strings with the + operator to produce a new string:
let name = "John"let surname = "Appleseed"let fullName = name + " " + surname // fullName is "John Appleseed"Append to a mutable string using the += compound assignment operator, or using a method:
let str2 = "there"var instruction = "look over"instruction += " " + str2 // instruction is now "look over there"
var instruction = "look over"instruction.append(" " + str2) // instruction is now "look over there"Append a single character to a mutable String:
var greeting: String = "Hello"let exclamationMark: Character = "!"greeting.append(exclamationMark)// produces a modified String (greeting) = "Hello!"Append multiple characters to a mutable String
var alphabet:String = "my ABCs: "alphabet.append(contentsOf: (0x61...0x7A).map(UnicodeScalar.init) .map(Character.init) )// produces a modified string (alphabet) = "my ABCs: abcdefghijklmnopqrstuvwxyz"appendContentsOf(_:) has been renamed to append(_:).
Join a sequence of strings to form a new string using joinWithSeparator(_:):
let words = ["apple", "orange", "banana"]let str = words.joinWithSeparator(" & ")
print(str) // "apple & orange & banana"joinWithSeparator(_:) has been renamed to joined(separator:).
The separator is the empty string by default, so ["a", "b", "c"].joined() == "abc".
String Encoding and Decomposition
Section titled “String Encoding and Decomposition”A Swift String is made of Unicode code points. It can be decomposed and encoded in several different ways.
let str = "ที่👌①!"Decomposing Strings
Section titled “Decomposing Strings”A string’s characters are Unicode extended grapheme clusters:
Array(str.characters) // ["ที่", "👌", "①", "!"]The unicodeScalars are the Unicode code points that make up a string (notice that ที่ is one grapheme cluster, but 3 code points — 3607, 3637, 3656 — so the length of the resulting array is not the same as with characters):
str.unicodeScalars.map{ $0.value } // [3607, 3637, 3656, 128076, 9312, 33]You can encode and decompose strings as UTF-8 (a sequence of UInt8s) or UTF-16 (a sequence of UInt16s):
Array(str.utf8) // [224, 184, 151, 224, 184, 181, 224, 185, 136, 240, 159, 145, 140, 226, 145, 160, 33]Array(str.utf16) // [3607, 3637, 3656, 55357, 56396, 9312, 33]String Length and Iteration
Section titled “String Length and Iteration”A string’s characters, unicodeScalars, utf8, and utf16 are all Collections, so you can get their count and iterate over them:
// NOTE: These operations are NOT necessarily fast/cheap!
str.characters.count // 4str.unicodeScalars.count // 6str.utf8.count // 17str.utf16.count // 7for c in str.characters { // ...for u in str.unicodeScalars { // ...for byte in str.utf8 { // ...for byte in str.utf16 { // ...Examine and compare strings
Section titled “Examine and compare strings”Check whether a string is empty:
if str.isEmpty { // do something if the string is empty}
// If the string is empty, replace it with a fallback:let result = str.isEmpty ? "fallback string" : strCheck whether two strings are equal (in the sense of Unicode canonical equivalence):
"abc" == "def" // false"abc" == "ABC" // false"abc" == "abc" // true
// "LATIN SMALL LETTER A WITH ACUTE" == "LATIN SMALL LETTER A" + "COMBINING ACUTE ACCENT""\u{e1}" == "a\u{301}" // trueCheck whether a string starts/ends with another string:
"fortitude".hasPrefix("fort") // true"Swift Language".hasSuffix("age") // trueReversing Strings
Section titled “Reversing Strings”let aString = "This is a test string."
// first, reverse the String's characterslet reversedCharacters = aString.characters.reverse()
// then convert back to a String with the String() initializerlet reversedString = String(reversedCharacters)
print(reversedString) // ".gnirts tset a si sihT"let reversedCharacters = aString.characters.reversed()let reversedString = String(reversedCharacters)Check if String contains Characters from a Defined Set
Section titled “Check if String contains Characters from a Defined Set”Letters
let letters = CharacterSet.letters
let phrase = "Test case"let range = phrase.rangeOfCharacter(from: letters)
// range will be nil if no letters is foundif let test = range { print("letters found")}else { print("letters not found")}let letters = NSCharacterSet.letterCharacterSet()
let phrase = "Test case"let range = phrase.rangeOfCharacterFromSet(letters)
// range will be nil if no letters is foundif let test = range { print("letters found")}else { print("letters not found")}The new CharacterSet struct that is also bridged to the Objective-C NSCharacterSet class define several predefined sets as:
decimalDigitscapitalizedLettersalphanumericscontrolCharactersillegalCharacters- and more you can find in the NSCharacterSet reference.
You also can define your own set of characters:
let phrase = "Test case"let charset = CharacterSet(charactersIn: "t")
if let _ = phrase.rangeOfCharacter(from: charset, options: .caseInsensitive) { print("yes")}else { print("no")}let charset = NSCharacterSet(charactersInString: "t")
if let _ = phrase.rangeOfCharacterFromSet(charset, options: .CaseInsensitiveSearch, range: nil) { print("yes")}else { print("no")}You can also include range:
let phrase = "Test case"let charset = CharacterSet(charactersIn: "t")
if let _ = phrase.rangeOfCharacter(from: charset, options: .caseInsensitive, range: phrase.startIndex..<phrase.endIndex)) { print("yes")}else { print("no")}String Iteration
Section titled “String Iteration”let string = "My fantastic string"var index = string.startIndex
while index != string.endIndex { print(string[index]) index = index.successor()}Note: endIndex is after the end of the string (i.e. string[string.endIndex] is an error, but string[string.startIndex] is fine). Also, in an empty string (""), string.startIndex == string.endIndex is true. Be sure to check for empty strings, since you cannot call startIndex.successor() on an empty string.
In Swift 3, String indexes no longer have successor(), predecessor(), advancedBy(_:), advancedBy(_:limit:), or distanceTo(_:).
Instead, those operations are moved to the collection, which is now responsible for incrementing and decrementing its indices.
Available methods are .index(after:), .index(before:) and .index(_:, offsetBy:).
let string = "My fantastic string"var currentIndex = string.startIndex
while currentIndex != string.endIndex { print(string[currentIndex]) currentIndex = string.index(after: currentIndex)}Note: we’re using currentIndex as a variable name to avoid confusion with the .index method.
And, for example, if you want to go the other way:
var index:String.Index? = string.endIndex.predecessor()
while index != nil { print(string[index!]) if index != string.startIndex { index = index.predecessor() } else { index = nil }}(Or you could just reverse the string first, but if you don’t need to go all the way through the string you probably would prefer a method like this)
var currentIndex: String.Index? = string.index(before: string.endIndex)
while currentIndex != nil { print(string[currentIndex!]) if currentIndex != string.startIndex { currentIndex = string.index(before: currentIndex!) } else { currentIndex = nil }}Note, Index is an object type, and not an Int. You cannot access a character of string as follows:
let string = "My string"string[2] // can't do thisstring.characters[2] // and also can't do thisBut you can get a specific index as follows:
index = string.startIndex.advanceBy(2)currentIndex = string.index(string.startIndex, offsetBy: 2)And can go backwards like this:
index = string.endIndex.advancedBy(-2)currentIndex = string.index(string.endIndex, offsetBy: -2)If you might exceed the string’s bounds, or you want to specify a limit you can use:
index = string.startIndex.advanceBy(20, limit: string.endIndex)currentIndex = string.index(string.startIndex, offsetBy: 20, limitedBy: string.endIndex)Alternatively one can just iterate through the characters in a string, but this might be less useful depending on the context:
for c in string.characters { print(c)}Unicode
Section titled “Unicode”Setting values
Section titled “Setting values”Using Unicode directly
var str: String = "I want to visit 北京, Москва, मुंबई, القاهرة, and 서울시. 😊"var character: Character = "🌍"Using hexadecimal values
var str: String = "\u{61}\u{5927}\u{1F34E}\u{3C0}" // a大🍎πvar character: Character = "\u{65}\u{301}" // é = "e" + accent markNote that the Swift Character can be composed of multiple Unicode code points, but appears to be a single character. This is called an Extended Grapheme Cluster.
Conversions
Section titled “Conversions”String —> Hex
// Accesses views of different Unicode encodings of `str`str.utf8str.utf16str.unicodeScalars // UTF-32Hex —> String
let value0: UInt8 = 0x61let value1: UInt16 = 0x5927let value2: UInt32 = 0x1F34E
let string0 = String(UnicodeScalar(value0)) // alet string1 = String(UnicodeScalar(value1)) // 大let string2 = String(UnicodeScalar(value2)) // 🍎
// convert hex array to Stringlet myHexArray = [0x43, 0x61, 0x74, 0x203C, 0x1F431] // an Int arrayvar myString = ""for hexValue in myHexArray { myString.append(UnicodeScalar(hexValue))}print(myString) // Cat‼🐱Note that for UTF-8 and UTF-16 the conversion is not always this easy because things like emoji cannot be encoded with a single UTF-16 value. It takes a surrogate pair.
Splitting a String into an Array
Section titled “Splitting a String into an Array”In Swift you can easily separate a String into an array by slicing it at a certain character:
let startDate = "23:51"
let startDateAsArray = startDate.components(separatedBy: ":") // ["23", "51"]`let startDate = "23:51"
let startArray = startDate.componentsSeparatedByString(":") // ["23", "51"]`Or when the separator isn’t present:
let myText = "MyText"
let myTextArray = myText.components(separatedBy: " ") // myTextArray is ["MyText"]let myText = "MyText"
let myTextArray = myText.componentsSeparatedByString(" ") // myTextArray is ["MyText"]Uppercase and Lowercase Strings
Section titled “Uppercase and Lowercase Strings”To make all the characters in a String uppercase or lowercase:
let text = "AaBbCc"let uppercase = text.uppercaseString // "AABBCC"let lowercase = text.lowercaseString // "aabbcc"let text = "AaBbCc"let uppercase = text.uppercased() // "AABBCC"let lowercase = text.lowercased() // "aabbcc"Formatting Strings
Section titled “Formatting Strings”Leading Zeros
Section titled “Leading Zeros”let number: Int = 7let str1 = String(format: "%03d", number) // 007let str2 = String(format: "%05d", number) // 00007Numbers after Decimal
Section titled “Numbers after Decimal”let number: Float = 3.14159let str1 = String(format: "%.2f", number) // 3.14let str2 = String(format: "%.4f", number) // 3.1416 (rounded)Decimal to Hexadecimal
Section titled “Decimal to Hexadecimal”let number: Int = 13627let str1 = String(format: "%2X", number) // 353Blet str2 = String(format: "%2x", number) // 353b (notice the lowercase b)Alternatively one could use specialized initializer that does the same:
let number: Int = 13627let str1 = String(number, radix: 16, uppercase: true) //353Blet str2 = String(number, radix: 16) // 353bDecimal to a number with arbitrary radix
Section titled “Decimal to a number with arbitrary radix”let number: Int = 13627let str1 = String(number, radix: 36) // aijRadix is Int in [2, 36].
Converting Swift string to a number type
Section titled “Converting Swift string to a number type”Int("123") // Returns 123 of Int typeInt("abcd") // Returns nilInt("10") // Returns 10 of Int typeInt("10", radix: 2) // Returns 2 of Int typeDouble("1.5") // Returns 1.5 of Double typeDouble("abcd") // Returns nilNote that doing this returns an Optional value, which should be unwrapped accordingly before being used.
Convert String to and from Data / NSData
Section titled “Convert String to and from Data / NSData”To convert String to and from Data / NSData we need to encode this string with a specific encoding. The most famous one is UTF-8 which is an 8-bit representation of Unicode characters, suitable for transmission or storage by ASCII-based systems. Here is a list of all available String Encodings
String to Data/NSData
let data = string.data(using: .utf8)let data = string.dataUsingEncoding(NSUTF8StringEncoding)Data/NSData to String
let string = String(data: data, encoding: .utf8)let string = String(data: data, encoding: NSUTF8StringEncoding)Count occurrences of a Character into a String
Section titled “Count occurrences of a Character into a String”Given a String and a Character
let text = "Hello World"let char: Character = "o"We can count the number of times the Character appears into the String using
let sensitiveCount = text.characters.filter { $0 == char }.count // case-sensitivelet insensitiveCount = text.lowercaseString.characters.filter { $0 == Character(String(char).lowercaseString) } // case-insensitiveRemove characters from a string not defined in Set
Section titled “Remove characters from a string not defined in Set”func removeCharactersNotInSetFromText(text: String, set: Set<Character>) -> String { return String(text.characters.filter { set.contains( $0) })}
let text = "Swift 3.0 Come Out"var chars = Set([Character]("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters))let newText = removeCharactersNotInSetFromText(text, set: chars) // "SwiftComeOut"func removeCharactersNotInSetFromText(text: String, set: Set<Character>) -> String { return String(text.characters.filter { set.contains( $0) })}
let text = "Swift 3.0 Come Out"var chars = Set([Character]("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters))let newText = removeCharactersNotInSetFromText(text: text, set: chars)Remove leading and trailing WhiteSpace and NewLine
Section titled “Remove leading and trailing WhiteSpace and NewLine”let someString = " Swift Language \n"let trimmedString = someString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())// "Swift Language"Method stringByTrimmingCharactersInSet returns a new string made by removing from both ends of the String characters contained in a given character set.
We can also just remove only whitespace or newline.
Removing only whitespace:
let trimmedWhiteSpace = someString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())// "Swift Language \n"Removing only newline:
let trimmedNewLine = someString.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())// " Swift Language "let someString = " Swift Language \n"
let trimmedString = someString.trimmingCharacters(in: .whitespacesAndNewlines)// "Swift Language"
let trimmedWhiteSpace = someString.trimmingCharacters(in: .whitespaces)// "Swift Language \n"
let trimmedNewLine = someString.trimmingCharacters(in: .newlines)// " Swift Language "Note: all these methods belong to Foundation. Use import Foundation if Foundation isn’t already imported via other libraries like Cocoa or UIKit.
Syntax
Section titled “Syntax”- String.characters // Returns an Array of the characters in the String
- String.characters.count // Returns the number of characters
- String.utf8 // A String.UTF8View, returns the UTF-8 character points in the String
- String.utf16 // A String.UTF16View, returns the UTF-16 character points in the String
- String.unicodeScalars // A String.UnicodeScalarView, returns the UTF-32 character points in the String
- String.isEmpty // Returns true if the String does not contain any text
- String.hasPrefix(String) // Returns true if the String is prefixed with the argument
- String.hasSuffix(String) // Returns true if the String is suffixed with the argument
- String.startIndex // Returns the Index that corresponds to the first character in the string
- String.endIndex // Returns the Index that corresponds to the spot after the last character in the string
- String.components(separatedBy: String) // Returns an array containing the substrings separated by the given separator string
- String.append(Character) // Adds the character (given as argument) to the String
Remarks
Section titled “Remarks”A String in Swift is a collection of characters, and by extension a collection of Unicode scalars. Because Swift Strings are based on Unicode, they may be any Unicode scalar value, including languages other than English and emojis.
Because two scalars could combine to form a single character, the number of scalars in a String is not necessarily always the same as the number of characters.
For more information about Strings, see The Swift Programming Language and the String Structure Reference.
For implementation details, see “Swift String Design”