標籤:des http 使用 os 檔案 io for art
String 是一個有序的字元集合,例如 "hello, world", "albatross"。Swift 字串通過 String 類型來表示,也可以表示為 Character 類型值的集合。
Swift 的 String 和 Character 類型提供了一個快速的,相容 Unicode 的方式來處理代碼中的文本資訊。建立和操作字串的文法與 C的操作方式相似,輕量並且易讀。字串串連操作只需要簡單地通過 + 號將兩個字串相連即可。與 Swift 中其他值一樣,能否更改字串的值,取決於其被定義為常量還是變數。
儘管文法簡易,但 String 類型是一種快速、現代化的字串實現。每一個字串都是由獨立編碼的 Unicode 字元組成,並提供了用於訪問這些字元在不同的Unicode表示的支援。
String 也可以用於在常量、變數、字面量和運算式中進行字串插值,這使得建立用於展示、儲存和列印的字串變得輕鬆自如。
注意:Swift 的 String 類型與 Foundation NSString 類進行了無縫橋接。如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 架構進行工作,整個 NSString API 都可以調用您建立的任意 String 類型的值,您額外還可以在任意 API 中使用本章介紹的 String 特性。您也可以在任意要求傳入NSString 執行個體作為參數的 API 中使用 String 類型的值進行替換。
更多關於在 Foundation 和 Cocoa 中使用 String 的資訊請查看 Using Swift with Cocoa and Objective-C。
字串字面量
您可以在您的代碼中包含一段預定義的字串值作為字串字面量。字串字面量是由雙引號包裹著的具有固定順序的文本字元集。
字串字面量可以用於為常量和變數提供初始值。
- let someString = "Some string literal value"
注意:someString 變數通過字串字面量進行初始化,Swift 因此推斷其為 String 類型。
字串字面量可以包含以下特殊字元:
- 轉移特殊字元 \0 (Null 字元)、\\(反斜線)、\t (水平定位字元)、\n (分行符號)、\r (斷行符號符)、\" (雙引號)、\‘ (單引號)。
- 單位元組 Unicode 標量,寫成 \xnn,其中 nn 為兩位十六進位數。
- 雙位元組 Unicode 標量,寫成 \unnnn,其中 nnnn 為四位十六進位數。
- 四位元組 Unicode 標量,寫成 \Unnnnnnnn,其中 nnnnnnnn 為八位十六進位數。
下面的代碼為各種特殊字元的使用樣本。
wiseWords 常量包含了兩個轉移特殊字元 (雙括弧);dollarSign、blackHeart 和 sparklingHeart 常量示範了三種不同格式的 Unicode 標量:
- let wiseWords = "\"我是要成為海賊王的男人\" - 路飛"
- // "我是要成為海賊王的男人" - 路飛
- let dollarSign = "\x24" // $, Unicode 標量 U+0024
- let blackHeart = "\u2665" // ♥, Unicode 標量 U+2665
- let sparklingHeart = "\U0001F496" // ??, Unicode 標量 U+1F496
初始化Null 字元串
為了構造一個很長的字串,可以建立一個Null 字元串作為初始值。可以將空的字串字面量賦值給變數,也可以初始化一個新的String 執行個體:
- var emptyString = "" // Null 字元串字面量
- var anotherEmptyString = String() // 初始化 String 執行個體
- // 兩個字串均為空白並等價。
您可以通過檢查其 Boolean 類型的 isEmpty 屬性來判斷該字串是否為空白:
- if emptyString.isEmpty {
- println("什麼都沒有")
- }
- // 列印輸出:"什麼都沒有"
字串可變性
您可以通過將一個特定字串分配給一個變數來對其進行修改,或者分配給一個常量來保證其不會被修改:
- var variableString = "Horse"
- variableString += " and carriage" // variableString 現在為 "Horse and carriage"
- let constantString = "Highlander"
- constantString += " and another Highlander" // 這會報告一個編譯錯誤(compile-time error) - 常量不可以被修改。
注意:在 Objective-C 和 Cocoa 中,您通過選擇兩個不同的類( NSString 和 NSMutableString )來指定該字串是否可以被修改,Swift中的字串是否可以修改僅通過定義的是變數還是常量來決定,實現了多種類型可變性操作的統一。
字串是實值型別
Swift 的 String 類型是實值型別。如果您建立了一個新的字串,那麼當其進行常量、變數賦值操作或在函數/方法中傳遞時,會進行值拷貝。任何情況下,都會對已有字串值建立新副本,並對該新副本進行傳遞或賦值。實值型別在 Structures and Enumerations Are Value Types 中進行了說明。
注意:其 Cocoa 中的 NSString 不同,當您在 Cocoa 中建立了一個 NSString 執行個體,並將其傳遞給一個函數/方法,或者賦值給一個變數,您永遠都是傳遞或賦值同一個 NSString 執行個體的一個引用。除非您特別要求其進行值拷貝,否則字串不會進行賦值新副本操作。
Swift 預設字串拷貝的方式保證了在函數/方法中傳遞的是字串的值,其明確了無論該值來自於哪裡,都是您獨自擁有的。您可以放心您傳遞的字串本身不會被更改。
在實際編譯時間,Swift編譯器會最佳化字串的使用,使實際的複製只發生在絕對必要的情況下,這意味著您始終可以將字串作為實值型別的同時獲得極高的效能。
使用字元(Characters)
Swift 的 String 類型表示特定序列的字元值的集合。每一個字元值代表一個 Unicode 字元。您可利用 for-in 迴圈來遍曆字串中的每一個字元:
- for character in "Dog!" {
- println(character)
- }
- // D
- // o
- // g
- // !
for-in 迴圈在For Loops中進行了詳細描述。
另外,通過標明一個 Character 類型註解並通過字元字面量進行賦值,可以建立一個獨立的字元常量或變數:
- let yenSign: Character = "¥"
計算字元數量
通過調用全域 countElements 函數並將字串作為參數進行傳遞可以擷取該字串的字元數量。
- let unusualMenagerie = "Koala ??, Snail ??, Penguin ??, Dromedary ??"
- println("unusualMenagerie has \(countElements(unusualMenagerie)) characters") // prints "unusualMenagerie has 40 characters"
注意:不同的 Unicode 字元以及相同 Unicode 字元的不同表示方式可能需要不同數量的記憶體空間來儲存,所以Swift 中的字元在一個字串中並不一定佔用相同的記憶體空間。因此,字串的長度不得不通過迭代字串中每一個字元的長度來進行計算。如果您正在處理一個長字串,需要注意 countElements 函數必須遍曆字串中的字元以精準計算字串的長度。
另外需要注意的是通過 countElements 返回的字元數量並不總是與包含相同字元的 NSString 的 length 屬性相同。NSString 的 length 屬性是基於利用 UTF-16 表示的十六位代碼單元數字,而不是基於 Unicode 字元。為瞭解決這個問題,NSString 的 length 屬性在被 Swift的 String 訪問時會成為 utf16count。
連接字串和字元
字串和字元的值可以通過加法運算子 (+) 相加在一起並建立一個新的字串值:
- let string1 = "hello"
- let string2 = " there"
- let character1: Character = "!"
- let character2: Character = "?"
- let stringPlusCharacter = string1 + character1 // 等於 "hello!"
- let stringPlusString = string1 + string2 // 等於 "hello there"
- let characterPlusString = character1 + string1 // 等於 "!hello"
- let characterPlusCharacter = character1 + character2 // 等於 "!?"
您也可以通過加法賦值運算子 (+=) 將一個字串或者字元添加到一個已經存在字串變數上:
- var instruction = "look over"
- instruction += string2
- // instruction 現在等於 "look over there"
- var welcome = "good morning"
- welcome += character1
- // welcome 現在等於 "good morning!"
注意:您不能將一個字串或者字元添加到一個已經存在的字元變數上,因為字元變數只能包含一個字元。
字串插值
字串插值是一種全新的構建字串的方式,可以在其中包含常量、變數、字面量和運算式。您插入的字串字面量的每一項都被包裹在以反斜線為首碼的圓括弧中:
- let multiplier = 3
- let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
- // message is "3 times 2.5 is 7.5"
在上面的例子中,multiplier 作為 \(multiplier) 被插入到一個字串字面量中。當建立字串執行插值計算時此預留位置會被替換為 multiplier 實際的值。
multiplier 的值也作為字串中後面運算式的一部分。該運算式計算 Double(multiplier) * 2.5 的值並將結果 (7.5) 插入到字串中。在這個例子中,運算式寫為 \(Double(multiplier) * 2.5) 並包含在字串字面量中。
注意:您插值字串中寫在括弧中的運算式不能包含非轉義雙引號 (") 和反斜線 (\),並且不能包含斷行符號或分行符號。
比較字串
Swift 提供了三種方式來比較字串的值:字串相等,首碼相等和尾碼相等。
字串相等
如果兩個字串以同一順序包含完全相同的字元,則認為兩者字串相等:
- let quotation = "We‘re a lot alike, you and I."
- let sameQuotation = "We‘re a lot alike, you and I."
- if quotation == sameQuotation {
- println("These two strings are considered equal")
- }
- // prints "These two strings are considered equal"
首碼/尾碼相等
通過調用字串的 hasPrefix/hasSuffix 方法來檢查字串是否擁有特定首碼/尾碼。兩個方法均需要以字串作為參數傳入並傳出 Boolean 值。兩個方法均執行基底字元串和首碼/尾碼字串之間逐個字元的比較操作。
下面的例子以一個字串數組表示莎士比亞話劇 羅密歐與朱麗葉 中前兩場的情境位置:
- 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 方法來計算話劇中第一幕的情境數:
- var act1SceneCount = 0
- for scene in romeoAndJuliet {
- if scene.hasPrefix("Act 1 ") {
- ++act1SceneCount
- }
- }
- println("There are \(act1SceneCount) scenes in Act 1")
- // prints "There are 5 scenes in Act 1"
大寫和小寫字串
您可以通過字串的 uppercaseString 和 lowercaseString 屬性來訪問一個字串的大寫/小寫版本。
- 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
Unicode 是文本編碼和表示的國際標準。它使您可以用標準格式表示來自任意語言幾乎所有的字元,並能夠對文字檔或網頁這樣的外部資源中的字元進行讀寫操作。
Swift 的字串和字元類型是完全相容 Unicode 的,它支援如下所述的一系列不同的 Unicode 編碼。
Unicode 術語(Terminology)
Unicode 中每一個字元都可以被解釋為一個或多個 unicode 標量。字元的 unicode 標量是一個唯一的21位元字(和名稱),例如U+0061 表示小寫拉丁字母A ("a"),U+1F425 表示正面站立的雞寶寶 ("??")
當 Unicode 字串被寫進文字檔或其他儲存結構當中,這些 unicode 標量將會按照 Unicode 定義的集中格式之一進行編碼。其包括 UTF-8 (以8位代碼單元進行編碼) 和 UTF-16 (以16位代碼單元進行編碼)。
字串的 Unicode 表示
Swift 提供了幾種不同的方式來訪問字串的 Unicode 表示。
您可以利用 for-in 來對字串進行遍曆,從而以 Unicode 字元的方式訪問每一個字元值。該過程在 Working with Characters 中進行了描述。
另外,能夠以其他三種 Unicode 相容的方式訪問字串的值:
- UTF-8 代碼資料格集合 (利用字串的 utf8 屬性進行訪問)
- UTF-16 代碼資料格集合 (利用字串的 utf16 屬性進行訪問)
- 21位的 Unicode 標量值集合 (利用字串的 unicodeScalars 屬性進行訪問)
下面由 D o g ! 和 ?? (狗臉表情,Unicode 標量為 U+1F436)組成的字串中的每一個字元代表著一種不同的表示:
- let dogString = "Dog!??"
UTF-8
您可以通過遍曆字串的 utf8 屬性來訪問它的 UTF-8 表示。其為 UTF8View 類型的屬性,UTF8View 是無符號8位 (UInt8) 值的集合,每一個 UIn8 都是一個字元的 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) 是 狗臉表情 的4位 UTF-8 表示。
UTF-16
您可以通過遍曆字串的 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 and 56374) 是 狗臉表情 字元的UTF-16 表示。第一個值為 U+D83D (十進位值為 55357),第二個值為 U+DC36 (十進位值為 56374)。
Unicode 標量 (Scalars)
您可以通過遍曆字串的 unicodeScalars 屬性來訪問它的 Unicode 標量表示。其為 UnicodeScalarView 類型的屬性,UnicodeScalarView 是 UnicodeScalar 的集合。UnicodeScalar 是21位的 Unicode 代碼點。
每一個 UnicodeScalar 擁有一個值屬性,可以返回對應的21位元值,用 UInt32 來表示。
- for scalar in dogString.unicodeScalars {
- print("\(scalar.value) ")
- }
- print("\n")
- // 68 111 103 33 128054
同樣,前四個代碼單元值 (68, 111, 103, 33) 代表了字元 D o g 和 ! 。第五位元值,128054,是一個十六進位1F436的十進位表示。其等同於 狗臉表情 的Unicode 標量 U+1F436。
作為查詢字元值屬性的一種替代方法,每個 UnicodeScalar 值也可以用來構建一個新的字串值,比如在字串插值中使用:
複製純文字新視窗
- for scalar in dogString.unicodeScalars {
- println("\(scalar) ")
- }
- // D
- // o
- // g
- // !
- // ??