String
是例如“hello, world”,“海賊王” 這樣的有序的Character
(字符)類型的值的集合,通過String
類型來表示。
Swift 的String
和Character
類型提供了一個快速的,兼容 Unicode 的方式來處理代碼中的文本信息。創(chuàng)建和操作字符串的語法與 C 語言中字符串操作相似,輕量并且易讀。字符串連接操作只需要簡單地通過+
號將兩個字符串相連即可。與 Swift 中其他值一樣,能否更改字符串的值,取決于其被定義為常量還是變量。
盡管語法簡易,但String
類型是一種快速、現(xiàn)代化的字符串實現(xiàn)。每一個字符串都是由獨立編碼的 Unicode 字符組成,并提供了以不同 Unicode 表示(representations)來訪問這些字符的支持。
Swift 可以在常量、變量、字面量和表達式中進行字符串插值操作,可以輕松創(chuàng)建用于展示、存儲和打印的自定義字符串。
注意:
Swift 的String
類型與 FoundationNSString
類進行了無縫橋接。如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 框架進行工作。所有NSString
API 都可以調(diào)用您創(chuàng)建的任意String
類型的值。除此之外,還可以使用本章介紹的String
特性。您也可以在任意要求傳入NSString
實例作為參數(shù)的 API 中使用String
類型的值作為替代。更多關于在 Foundation 和 Cocoa 中使用String
的信息請查看 Using Swift with Cocoa and Objective-C。
您可以在您的代碼中包含一段預定義的字符串值作為字符串字面量。字符串字面量是由雙引號 ("") 包裹著的具有固定順序的文本字符集。
字符串字面量可以用于為常量和變量提供初始值。
let someString = "Some string literal value"
注意:
someString
常量通過字符串字面量進行初始化,Swift 因此推斷該常量為String
類型。
字符串字面量可以包含以下特殊字符:
\0
(空字符)、\\
(反斜線)、\t
(水平制表符)、\n
(換行符)、\r
(回車符)、\"
(雙引號)、\'
(單引號)。\u{n}
(u為小寫),其中n
為任意的一到八位十六進制數(shù)。下面的代碼為各種特殊字符的使用示例。wiseWords
常量包含了兩個轉(zhuǎn)移特殊字符 (雙括號);dollarSign
、blackHeart
和sparklingHeart
常量演示了三種不同格式的 Unicode 標量:
let wiseWords = "\"我是要成為海賊王的男人\" - 路飛"
// "我是要成為海賊王的男人" - 路飛
let dollarSign = "\u{24}" // $, Unicode 標量 U+0024
let blackHeart = "\u{2665}" // ?, Unicode 標量 U+2665
let sparklingHeart = "\u{1F496}" // ????, Unicode 標量 U+1F496
為了構造一個很長的字符串,可以創(chuàng)建一個空字符串作為初始值??梢詫⒖盏淖址置媪抠x值給變量,也可以初始化一個新的String
實例:
var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化 String 實例
// 兩個字符串均為空并等價。
您可以通過檢查其Boolean
類型的isEmpty
屬性來判斷該字符串是否為空:
if emptyString.isEmpty {
println("什么都沒有")
}
// 打印輸出:"什么都沒有"
您可以通過將一個特定字符串分配給一個變量來對其進行修改,或者分配給一個常量來保證其不會被修改:
var variableString = "Horse"
variableString += " and carriage"
// variableString 現(xiàn)在為 "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// 這會報告一個編譯錯誤 (compile-time error) - 常量不可以被修改。
注意:
在 Objective-C 和 Cocoa 中,您通過選擇兩個不同的類(NSString
和NSMutableString
)來指定該字符串是否可以被修改,Swift 中的字符串是否可以修改僅通過定義的是變量還是常量來決定,實現(xiàn)了多種類型可變性操作的統(tǒng)一。
Swift 的String
類型是值類型。如果您創(chuàng)建了一個新的字符串,那么當其進行常量、變量賦值操作或在函數(shù)/方法中傳遞時,會進行值拷貝。任何情況下,都會對已有字符串值創(chuàng)建新副本,并對該新副本進行傳遞或賦值操作。值類型在 結構體和枚舉是值類型 中進行了說明。
注意:
與 Cocoa 中的NSString
不同,當您在 Cocoa 中創(chuàng)建了一個NSString
實例,并將其傳遞給一個函數(shù)/方法,或者賦值給一個變量,您傳遞或賦值的是該NSString
實例的一個引用,除非您特別要求進行值拷貝,否則字符串不會生成新的副本來進行賦值操作。
Swift 默認字符串拷貝的方式保證了在函數(shù)/方法中傳遞的是字符串的值。很明顯無論該值來自于哪里,都是您獨自擁有的。您可以放心您傳遞的字符串本身不會被更改。
在實際編譯時,Swift 編譯器會優(yōu)化字符串的使用,使實際的復制只發(fā)生在絕對必要的情況下,這意味著您將字符串作為值類型的同時可以獲得極高的性能。
Swift 的String
類型表示特定序列的Character
(字符) 類型值的集合。每一個字符值代表一個 Unicode 字符。您可利用for-in
循環(huán)來遍歷字符串中的每一個字符:
for character in "Dog!????" {
println(character)
}
// D
// o
// g
// !
// ????
for-in 循環(huán)在 For Loops 中進行了詳細描述。
另外,通過標明一個Character
類型注解并通過字符字面量進行賦值,可以建立一個獨立的字符常量或變量:
let yenSign: Character = "¥"
通過調(diào)用全局countElements
函數(shù),并將字符串作為參數(shù)進行傳遞,可以獲取該字符串的字符數(shù)量。
let unusualMenagerie = "Koala ????, Snail ????, Penguin ????, Dromedary ????"
println("unusualMenagerie has \(countElements(unusualMenagerie)) characters")
// 打印輸出:"unusualMenagerie has 40 characters"
注意:
不同的 Unicode 字符以及相同 Unicode 字符的不同表示方式可能需要不同數(shù)量的內(nèi)存空間來存儲。所以 Swift 中的字符在一個字符串中并不一定占用相同的內(nèi)存空間。因此字符串的長度不得不通過迭代字符串中每一個字符的長度來進行計算。如果您正在處理一個長字符串,需要注意countElements
函數(shù)必須遍歷字符串中的字符以精準計算字符串的長度。另外需要注意的是通過countElements
返回的字符數(shù)量并不總是與包含相同字符的NSString
的length
屬性相同。NSString
的length
屬性是基于利用 UTF-16 表示的十六位代碼單元數(shù)字,而不是基于 Unicode 字符。為了解決這個問題,NSString
的length
屬性在被 Swift 的String
訪問時會成為utf16count
。
字符串可以通過加法運算符(+
)相加在一起(或稱“串聯(lián)”)并創(chuàng)建一個新的字符串:
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome 現(xiàn)在等于 "hello there"
您也可以通過加法賦值運算符 (+=
) 將一個字符串添加到一個已經(jīng)存在字符串變量上:
var instruction = "look over"
instruction += string2
// instruction 現(xiàn)在等于 "look over there"
你可以用將append
方法將一個字符附加到一個字符串變量的尾部:
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome 現(xiàn)在等于 "hello there!"
注意:
您不能將一個字符串或者字符添加到一個已經(jīng)存在的字符變量上,因為字符變量只能包含一個字符。
字符串插值是一種構建新字符串的方式,可以在其中包含常量、變量、字面量和表達式。您插入的字符串字面量的每一項都被包裹在以反斜線為前綴的圓括號中:
let multiplier = 3
let message = "\(multiplier) 乘以 2.5 是 \(Double(multiplier) * 2.5)"
// message 是 "3 乘以 2.5 是 7.5"
在上面的例子中,multiplier
作為\(multiplier)
被插入到一個字符串字面量中。當創(chuàng)建字符串執(zhí)行插值計算時此占位符會被替換為multiplier
實際的值。
multiplier
的值也作為字符串中后面表達式的一部分。該表達式計算Double(multiplier) * 2.5
的值并將結果 (7.5) 插入到字符串中。在這個例子中,表達式寫為\(Double(multiplier) * 2.5)
并包含在字符串字面量中。
注意:
插值字符串中寫在括號中的表達式不能包含非轉(zhuǎn)義雙引號 ("
) 和反斜杠 (\
),并且不能包含回車或換行符。
Swift 提供了三種方式來比較字符串的值:字符串相等、前綴相等和后綴相等。
如果兩個字符串以同一順序包含完全相同的字符,則認為兩者字符串相等:
let quotation = "我們是一樣一樣滴."
let sameQuotation = "我們是一樣一樣滴."
if quotation == sameQuotation {
println("這兩個字符串被認為是相同的")
}
// 打印輸出:"這兩個字符串被認為是相同的"
通過調(diào)用字符串的hasPrefix
/hasSuffix
方法來檢查字符串是否擁有特定前綴/后綴。兩個方法均需要以字符串作為參數(shù)傳入并傳出Boolean
值。兩個方法均執(zhí)行基本字符串和前綴/后綴字符串之間逐個字符的比較操作。
下面的例子以一個字符串數(shù)組表示莎士比亞話劇《羅密歐與朱麗葉》中前兩場的場景位置:
let romeoAndJuliet = [
"Act 1 Scene 1: Verona, A public place",
"Act 1 Scene 2: Capulet's mansion",
"Act 1 Scene 3: A room in Capulet's mansion",
"Act 1 Scene 4: A street outside Capulet's mansion",
"Act 1 Scene 5: The Great Hall in Capulet's mansion",
"Act 2 Scene 1: Outside Capulet's mansion",
"Act 2 Scene 2: Capulet's orchard",
"Act 2 Scene 3: Outside Friar Lawrence's cell",
"Act 2 Scene 4: A street in Verona",
"Act 2 Scene 5: Capulet's mansion",
"Act 2 Scene 6: Friar Lawrence's cell"
]
您可以利用hasPrefix
方法來計算話劇中第一幕的場景數(shù):
var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
++act1SceneCount
}
}
println("There are \(act1SceneCount) scenes in Act 1")
// 打印輸出:"There are 5 scenes in Act 1"
相似地,您可以用hasSuffix
方法來計算發(fā)生在不同地方的場景數(shù):
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
if scene.hasSuffix("Capulet's mansion") {
++mansionCount
} else if scene.hasSuffix("Friar Lawrence's cell") {
++cellCount
}
}
println("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// 打印輸出:"6 mansion scenes; 2 cell scenes”
您可以通過字符串的uppercaseString
和lowercaseString
屬性來訪問大寫/小寫版本的字符串。
import Foundation
let normal = "Could you help me, please?"
let shouty = normal.uppercaseString
// shouty 值為 "COULD YOU HELP ME, PLEASE?"
let whispered = normal.lowercaseString
// whispered 值為 "could you help me, please?"
Unicode 是一個國際標準,用于文本的編碼和表示。它使您可以用標準格式表示來自任意語言幾乎所有的字符,并能夠?qū)ξ谋疚募蚓W(wǎng)頁這樣的外部資源中的字符進行讀寫操作。
Swift 的字符串和字符類型是完全兼容 Unicode 標準的,它支持如下所述的一系列不同的 Unicode 編碼。
Unicode 中每一個字符都可以被解釋為一個或多個 unicode 標量。字符的 unicode 標量是一個唯一的21位數(shù)字(和名稱),例如U+0061
表示小寫的拉丁字母A ("a"),U+1F425
表示小雞表情 ("????")
當 Unicode 字符串被寫進文本文件或其他存儲結構當中,這些 unicode 標量將會按照 Unicode 定義的集中格式之一進行編碼。其包括UTF-8
(以8位代碼單元進行編碼) 和UTF-16
(以16位代碼單元進行編碼)。
Swift 提供了幾種不同的方式來訪問字符串的 Unicode 表示。
您可以利用for-in
來對字符串進行遍歷,從而以 Unicode 字符的方式訪問每一個字符值。該過程在 使用字符 中進行了描述。
另外,能夠以其他三種 Unicode 兼容的方式訪問字符串的值:
utf8
屬性進行訪問)utf16
屬性進行訪問)unicodeScalars
屬性進行訪問)下面由D``o``g``!
和????
(DOG FACE
,Unicode 標量為U+1F436
)組成的字符串中的每一個字符代表著一種不同的表示:
let dogString = "Dog!????"
您可以通過遍歷字符串的utf8
屬性來訪問它的UTF-8
表示。其為UTF8View
類型的屬性,UTF8View
是無符號8位 (UInt8
) 值的集合,每一個UInt8
值都是一個字符的 UTF-8 表示:
for codeUnit in dogString.utf8 {
print("\(codeUnit) ")
}
print("\n")
// 68 111 103 33 240 159 144 182
上面的例子中,前四個10進制代碼單元值 (68, 111, 103, 33) 代表了字符D
o
g
和!
,它們的 UTF-8 表示與 ASCII 表示相同。后四個代碼單元值 (240, 159, 144, 182) 是DOG FACE
的4字節(jié) UTF-8 表示。
您可以通過遍歷字符串的utf16
屬性來訪問它的UTF-16
表示。其為UTF16View
類型的屬性,UTF16View
是無符號16位 (UInt16
) 值的集合,每一個UInt16
都是一個字符的 UTF-16 表示:
for codeUnit in dogString.utf16 {
print("\(codeUnit) ")
}
print("\n")
// 68 111 103 33 55357 56374
同樣,前四個代碼單元值 (68, 111, 103, 33) 代表了字符D
o
g
和!
,它們的 UTF-16 代碼單元和 UTF-8 完全相同。
第五和第六個代碼單元值 (55357 和 56374) 是DOG FACE
字符的UTF-16 表示。第一個值為U+D83D
(十進制值為 55357),第二個值為U+DC36
(十進制值為 56374)。
您可以通過遍歷字符串的unicodeScalars
屬性來訪問它的 Unicode 標量表示。其為UnicodeScalarView
類型的屬性, UnicodeScalarView
是UnicodeScalar
的集合。UnicodeScalar
是21位的 Unicode 代碼點。
每一個UnicodeScalar
擁有一個值屬性,可以返回對應的21位數(shù)值,用UInt32
來表示。
for scalar in dogString.unicodeScalars {
print("\(scalar.value) ")
}
print("\n")
// 68 111 103 33 128054
同樣,前四個代碼單元值 (68, 111, 103, 33) 代表了字符D
o
g
和!
。第五位數(shù)值,128054,是一個十六進制1F436的十進制表示。其等同于DOG FACE
的Unicode 標量 U+1F436。
作為查詢字符值屬性的一種替代方法,每個UnicodeScalar
值也可以用來構建一個新的字符串值,比如在字符串插值中使用:
for scalar in dogString.unicodeScalars {
println("\(scalar) ")
}
// D
// o
// g
// !
// ????
更多建議: