字符串是例如 "hello, world" , "albatross" 這樣的有序的Character (字符)類型的值的集合。通過String 類型來表示。 一個 String 的內(nèi)容可以用許多方式讀取,包括作為一個 Character值的集合。
Swift 的 String 類型與FoundationNSString 類進行了無縫橋接。Foundation 也可以對String進行擴 展,暴露在 NSString 中定義的方法。 這意味著,如果你在 String 中調(diào)用這些 NSString的方法,將不用進行 轉(zhuǎn)換。`
字符串字面量
字符串字面量是由雙引號 ( "" ) 包裹著的具 有固定順序的文本字符 。 字符串字面量可以用于為常量和變量提供初始值:
let someString = "Some string literal value"
注意 someString 常量通過字符串字面量進行初始化,Swift 會推斷該常量為 String 類型。
初始化空字符串
要創(chuàng)建一個空字符串作為初始值,可以將空的字符串字面量賦值給變量,也可以初始化一個新的 String實例:
var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化方法
// 兩個字符串均為空并等價。
您可以通過檢查其 Bool類型的 isEmpty 屬性來判斷該字符串是否為空:
if emptyString.isEmpty {
print("Nothing to see here")
}
// 打印輸出:"Nothing to see here"
字符串可變性
您可以通過將一個特定字符串分配給一個變量來對其進行修改,或者分配給一個常量來保證其不會被修改:
var variableString = "Horse"
variableString += " and carriage"
// variableString 現(xiàn)在為 "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// 這會報告一個編譯錯誤 (compile-time error) - 常量字符串不可以被修改。
字符串是值類型
Swift 的String類型是值類型。 如果您創(chuàng)建了一個新的字符串,那么當(dāng)其進行常量、變量賦值操作,或在函數(shù)/ 方法中傳遞時,會進行值拷貝。 任何情況下,都會對已有字符串值創(chuàng)建新副本,并對該新副本進行傳遞或賦值操作,這一點和OC有很大不同。
Swift 默認(rèn)字符串拷貝的方式保證了在函數(shù)/方法中傳遞的是字符串的值。 很明顯無論該值來自于哪里,都是您 獨自擁有的。 您可以確信傳遞的字符串不會被修改,除非你自己去修改它。
使用字符
可以通過forin 來遍歷字符串
for character in "Dog!?".characters {
print(character)
}
// D
// o
// g
// !
// ?
另外,通過標(biāo)明一個 Character 類型并用字符字面量進行賦值,可以建立一個獨立的字符常量或變量:
let exclamationMark: Character = "!"
字符串可以通過傳遞一個值類型為 Character的數(shù)組作為自變量來初始化:
let catCharacters: [Character] = ["C", "a", "t", "!", "?"] let catString = String(catCharacters)
print(catString)
// 打印輸出:"Cat!?"
連接字符串和字符
字符串可以通過加法運算符( + )相加在一起(或稱“連接”)創(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)存在的字符變量上,因為字符變量只能包含一個字符。
字符串插值
字符串插值是一種構(gòu)建新字符串的方式,可以在其中包含常量、變量、字面量和表達式。 您插入的字符串字面量 的每一項都在以反斜線為前綴的圓括號中:
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" // message 是 "3 times 2.5 is 7.5"
在上面的例子中,multiplier 作為\(multiplier)被插入到一個字符串常量量中。 當(dāng)創(chuàng)建字符串執(zhí)行插值計算 時此占位符會被替換為 multiplier 實際的值。multiplier的值也作為字符串中后面表達式的一部分。 該表達式計算 Double(multiplier) * 2.5的值并將結(jié)果( 7.5 ) 插入到字符串中。 在這個例子中,表達式寫為\(Double(multiplier) * 2.5) 并包含在字符串字面量中。
計算字符數(shù)量
如果想要獲得一個字符串中 Character值的數(shù)量,可以使用字符串的 characters 屬性的 count 屬性:
let unusualMenagerie = "Koala ?, Snail ?, Penguin ?, Dromedary ?"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// 打印輸出 "unusualMenagerie has 40 characters"
訪問和修改字符串
你可以通過字符串的屬性和方法來訪問和修改它,當(dāng)然也可以用下標(biāo)語法完成。
字符串索引
每一個 值都有一個關(guān)聯(lián)的索引(index)類型,String.index ,它對應(yīng)著字符串中的每一個 Character 的位置。
前面提到,不同的字符可能會占用不同數(shù)量的內(nèi)存空間,所以要知道 的確定位置,就必須從 開 頭遍歷每一個 Unicode 標(biāo)量直到結(jié)尾。因此,Swift的字符串不能用整數(shù)(integer)做索引。
使用 startIndex屬性可以獲取一個 String的第一個Character 的索引。使用endIndex 屬性可以獲取最后一個 Character的后一個位置的索引。因此,endIndex 屬性不能作為一個字符串的有效下標(biāo)。如果 String是空串,startIndex和 endIndex` 是相等的.
通過調(diào)用 String 的 index(before:)或 index(after:) 方法,可以立即得到前面或后面的一個索引。您還 可以通過調(diào)用 index(_:offsetBy:)方法來獲取對應(yīng)偏移量的索引,這種方式可以避免多次調(diào)用 index(befor e:) 或 index(after:)方法。
你可以使用下標(biāo)語法來訪問 String特定索引的 `Character 。
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.index(before: greeting.endIndex)]
// !
greeting[greeting.index(after: greeting.startIndex)]
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]
// a
試圖獲取越界索引對應(yīng)的Character,將引發(fā)一個運行時錯誤。
greeting[greeting.endIndex] // error
greeting.index(after: endIndex) // error
使用 characters屬性的indices 屬性會創(chuàng)建一個包含全部索引的范圍(Range),用來在一個字符串中訪問單 個字符。
for index in greeting.characters.indices {
print("\(greeting[index]) ", terminator: "")
}
// 打印輸出 "G u t e n T a g ! "
插入和刪除
調(diào)用insert(_:at:) 方法可以在一個字符串的指定索引插入一個字符,調(diào)用 insert(contentsOf:at:) 方法可 以在一個字符串的指定索引插入一個段字符串。
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex) // welcome 變量現(xiàn)在等于 "hello!"
welcome.insert(contentsOf:" there".characters, at: welcome.index(before: welcome.endIndex)) // welcome 變量現(xiàn)在等于 "hello there!"
調(diào)用remove(at:) 方法可以在一個字符串的指定索引刪除一個字符,調(diào)用 removeSubrange(_:)方法可以在一 個字符串的指定索引刪除一個子字符串。
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome 現(xiàn)在等于 "hello there"
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex welcome.removeSubrange(range)
// welcome 現(xiàn)在等于 "hello"
比較字符串
Swift 提供了三種方式來比較文本值:字符串字符相等、前綴相等和后綴相等。
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
print("These two strings are considered equal")
}
// 打印輸出 "These two strings are considered equal"
通過調(diào)用字符串的 hasPrefix(_:) / hasSuffix(_:)方法來檢查字符串是否擁有特定前綴/后綴,兩個方法均接收一 個 String 類型的參數(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"
]
var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
act1SceneCount += 1
} }
print("There are \(act1SceneCount) scenes in Act 1") // 打印輸出 "There are 5 scenes in Act 1"
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
if scene.hasSuffix("Capulet's mansion") {
mansionCount += 1
} else if scene.hasSuffix("Friar Lawrence's cell") {
cellCount += 1
} }
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// 打印輸出 "6 mansion scenes; 2 cell scenes"