Swift 3 學(xué)習(xí) - 03 字符串和字符

Swift 3.png
  • 1 .字符串字面量 String

在Swift中字符串字面量是由雙引號" " 包裹著的

let someString = "Some string literal value"

像我們在 Swift 3 學(xué)習(xí) 01 中講述的那樣良拼,Swift 會推斷該常量為String類型

  • 2 .初始化空字符串
    • 2.1 初始化

創(chuàng)建一個空字符串的兩種方式

//(1)可以將空的字符串字面量賦值給變量
var emptyString = "" // empty string literal
//(2)初始化一個新的String實例
var anotherEmptyString = String() // initializer syntax
// these two strings are both empty, and are equivalent to each other
    • 2.2 判斷空字符串

isEmpty 屬性來判斷該字符串是否為空,返回值為 Bool

var emptyString = ""
if emptyString.isEmpty {
print("Nothing to see here")
}
// Prints "Nothing to see here"
  • 3 .字符串可變性

在 Objective-C 中坤学,需要通過選擇兩個不同的類(NSString和NSMutableString)來指定字符串是否可以被修改米间。而在Swift中用 let 聲明常量來保證其不會被修改统求,用 var聲明變量來對其進行修改痹兜。

//可變的字符串
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"
//不可變的字符串
let constantString = "Highlander"
constantString += " and another Highlander"
// this reports a compile-time error - a constant string cannot be modified
3.0.png
  • 4 .字符串是值類型

Swift 的 String 類型是值類型再登。 如果創(chuàng)建了一個新的字符串方篮,那么當(dāng)其進行常量有缆、變量賦值操作象踊,或在函數(shù)/方法中傳遞時,會進行值拷貝棚壁。
這樣做的好處是杯矩,你可以確信傳遞的字符串不會被修改,除非你自己去修改它袖外。
在 Objective-C 中,你可能面臨著值被 '別人' 修改的風(fēng)險史隆,比如下面的 a .你并沒有去直接修改ta.

NSString * a;
NSMutableString * b = [@"111111" mutableCopy];
 a = b;
 [b appendString:@"222222"];
 NSLog(@"a = %@",a); //a = 111111222222

在Swift中,無論怎樣都不會將你的 a 修改 在刺,除非你直接對 a 進行修改逆害。

var a : String;
var b = "111111"
a = b;
b = b.appending("222222");
print("a = \\(a)\\n")          //輸出的 a = 111111
  • 5 . 使用字符 Character
    • 5.1 獲取字符串的字符

通過for-in循環(huán)來遍歷字符串中的characters屬性來獲取每一個字符的值.

for character in "Dog!".characters {
print(character)
}
// D
// o
// g
// !
// 
    • 5.2 聲明一個字符

通過Character 關(guān)鍵字聲明一個字符

let exclamationMark2: Character = "!"

必須要用Character聲明才能得到一個字符,否則會被Swift推斷為String類型蚣驼。

5.2.png

    • 5.3 用字符數(shù)組初始化一個字符串

字符串可以通過傳遞一個值類型為Character的數(shù)組作為自變量來初始化魄幕。

let catCharacters: [Character] = ["C", "a", "t", "!", ""]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!"
  • 6 .連接字符串和字符 ++=颖杏、append()

你可以不追加StringCharacter到現(xiàn)有的Character變量纯陨,因為一個Character值必須只包含一個字符。

    • 6.1 +

字符串可以通過加法運算符(+)相加在一起(或稱“連接”)創(chuàng)建一個新的字符串,在前面的文章提及過留储。

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"
    • 6.2 +=

可以通過加法賦值運算符 (+=) 將一個字符串添加到一個已經(jīng)存在字符串變量上

var instruction = "look over"
instruction += string2
// instruction now equals "look over there
    • 6.3 append()

可以用append()方法將一個字符附加到一個字符串變量的尾部

let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome now equals "hello there!"
  • 7 .字符串插值 \\(a)

Swift提供便利的方式在字符串中插入一些值翼抠。a可以是常量、變量获讳、字面量和表達式阴颖。 插入的字符串字面量的每一項都在以反斜線為前綴的圓括號中 即 \\(a)

let multiplier = 3
let message = "\\(multiplier) times 2.5 is \\(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"

在上述代碼中 \\(multiplier) 做為整體插入到字符串中,在系統(tǒng)讀取時會將對應(yīng)的值插入該位置丐膝。

  • 8 .Unicode

Unicode 是一個國際標準量愧,用于文本的編碼和表示钾菊。Swift 的String和Character類型是完全兼容 Unicode 標準的。

    • 8.1 Unicode 標量

Swift 的String類型是基于 Unicode 標量 建立的偎肃。 Unicode 標量是對應(yīng)字符或者修飾符的唯一的21位數(shù)字煞烫,例如U+0061表示小寫的拉丁字母("a"),U+1F425表示小雞表情("")累颂。
Unicode 碼位的范圍是U+0000U+D7FF或者U+E000U+10FFFF滞详。Unicode 標量不包括 Unicode 代理項(surrogate pair) 碼位,其碼位范圍是U+D800U+DFFF紊馏。

    • 8.2 字符串字面量的特殊字符
      字符串字面量可以包含以下特殊字符:
      轉(zhuǎn)義字符\\0(空字符)料饥、\\\\\\\\(反斜線)、\\t(水平制表符)瘦棋、\\n(換行符)稀火、\\r(回車符)、\\"(雙引號)赌朋、\\'(單引號)凰狞。
      Unicode 標量,寫成\\u{n}(u為小寫)沛慢,其中n為任意一到八位十六進制數(shù)且可用的 Unicode 位碼赡若。
let wiseWords = "\\"Imagination is more important than knowledge\\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\\u{24}" // $, Unicode scalar U+0024
let blackHeart = "\\u{2665}" // , Unicode scalar U+2665
let sparklingHeart = "\\u{1F496}" // , Unicode scalar U+1F496
  • 9 .計算字符數(shù)量 count

使用字符串的 characters 屬性的 count 屬性獲取字符數(shù)量。

let unusualMenagerie = "Koala , Snail , Penguin , Dromedary "  //只占一個字符团甲。
print("unusualMenagerie has \\(unusualMenagerie.characters.count) characters")
// Prints "unusualMenagerie has 40 characters"
  • 10 .可擴展的字形群集

每一個 Swift 的Character類型代表一個可擴展的字形群逾冬。 一個可擴展的字形群是一個或多個可生成人類可讀的字符 Unicode 標量的有序排列。
舉個例子躺苦,字母é可以用單一的 Unicode 標量é(LATIN SMALL LETTER E WITH ACUTE, 或者U+00E9)來表示身腻。
然而一個標準的字母e(LATIN SMALL LETTER E或者U+0065) 加上一個急促重音(COMBINING ACTUE ACCENT)的標量(U+0301),這樣一對標量就表示了同樣的字母é匹厘。 這個急促重音的標量形象的將e轉(zhuǎn)換成了é嘀趟。
簡單而言 e (U+0065) + U+0301 --> é(U+00E9)eAcutecombinedEAcute等價

let eAcute: Character = "\\u{E9}" // é
let combinedEAcute: Character = "\\u{65}\\u{301}" // e followed by ?
// eAcute is é, combinedEAcute is é

再比如在韓文中愈诚,下面的precomposeddecomposed等價

let precomposed: Character = "\\u{D55C}" // ?
let decomposed: Character = "\\u{1112}\\u{1161}\\u{11AB}" // ?, ?, ?
// precomposed is ?, decomposed is ?

再比如地域性指示符號的 Unicode 標量可以組合成一個單一的Character值

let regionalIndicatorForUS: Character = "\\u{1F1FA}\\u{1F1F8}"
// regionalIndicatorForUS is 
  • 11 .計算字符數(shù)量 count

通過characters屬性count屬性獲取字符數(shù)量她按, Swift 中的字符在一個字符串中并不一定占用相同的內(nèi)存空間數(shù)量。另外需要注意的是通過characters屬性返回的字符數(shù)量并不總是與包含相同字符的NSString的length屬性相同炕柔。NSString的length屬性是利用 UTF-16 表示的十六位代碼單元數(shù)字酌泰,而不是 Unicode 可擴展的字符群集。當(dāng)一個Swift的String值 被NSString的length屬性訪問時匕累,字符數(shù)量和字符串長度是不一樣的陵刹。

let unusualMenagerie = "Koala , Snail , Penguin , Dromedary "
print("unusualMenagerie has \\(unusualMenagerie.characters.count) characters")   
// Prints "unusualMenagerie has 40 characters"
//下面的代碼作為字符串算長度
var  str : NSString;
str = unusualMenagerie as NSString ;
print("str.length = \\(str.length)");    //str.length = 44
  • 12 . 字符串索引

每一個String值都有一個關(guān)聯(lián)的索引(index)類型,String.Index欢嘿,它對應(yīng)著字符串中的每一個Character的位置衰琐。
前面提到巡验,不同的字符可能會占用不同數(shù)量的內(nèi)存空間,所以要知道Character的確定位置碘耳,就必須從String開頭遍歷每一個 Unicode 標量直到結(jié)尾。因為整數(shù)(integer)是內(nèi)存空間的概念框弛,不同的字符可能會占用不同數(shù)量的內(nèi)存空間辛辨,Swift 的字符串不能用整數(shù)(integer)做索引。
使用startIndex屬性可以獲取一個String的第一個Character的索引瑟枫。使用endIndex屬性可以獲取最后一個Character的后一個位置的索引斗搞。因此,endIndex屬性不能作為一個字符串的有效下標慷妙。如果String是空串僻焚,startIndexendIndex是相等的。
通過調(diào)用 String 的 index(before:)index(after:)方法膝擂,可以立即得到前面或后面的一個索引虑啤。您還可以通過調(diào)用index(_:offsetBy:)方法來獲取對應(yīng)偏移量的索引,這種方式可以避免多次調(diào)用index(before:)index(after:) 方法架馋。

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ā)一個運行時錯誤
fatal error: Can't form a Character from an empty String

greeting[greeting.endIndex] // error
greeting.index(after: endIndex) // error

使用 characters 屬性的 indices 屬性會創(chuàng)建一個包含全部索引的范圍(Range),用來在一個字符串中訪問單個字符叉寂。

for index in greeting.characters.indices {
print("\\(greeting[index]) ", terminator: "")
}
// Prints "G u t e n T a g ! "
  • 13 .插入

調(diào)用insert(_:atIndex:)方法可以在一個字符串的指定索引插入一個字符萍启,調(diào)用 insert(contentsOf:at:) 方法可以在一個字符串的指定索引插入一段字符串。(用在遵循Collection協(xié)議的類型)

var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"
welcome.insert(contentsOf:" there".characters, at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
  • 14 .刪除

調(diào)用 remove(at:) 方法可以在一個字符串的指定索引刪除一個字符屏鳍,調(diào)用 removeSubrange(_:) 方法可以在一個字符串的指定索引刪除一個子字符串勘纯。(用在遵循RangeReplaceableCollection協(xié)議的類型)

welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"
  • 15 .比較字符串

Swift 提供了三種方式來比較文本值:字符串字符相等、前綴相等和后綴相等

    • 15.1 字符串/字符相等

字符串/字符可以用等于操作符(==)和不等于操作符(!=)

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")
}
// Prints "These two strings are considered equal"

如果兩個字符串(或者兩個字符)的可擴展的字形群集是標準相等的钓瞭,那就認為它們是相等的驳遵。在這個情況下,即使可擴展的字形群集是有不同的 Unicode 標量構(gòu)成的降淮,只要它們有同樣的語言意義和外觀超埋,就認為它們標準相等。
像上面提到的 e (U+0065) + U+0301 --> é(U+00E9)
這兩個字符群集都是表示字符é的有效方式佳鳖,所以它們被認為是標準相等霍殴。

// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\\u{E9}?"
// "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\\u{65}\\u{301}?"
if eAcuteQuestion == combinedEAcuteQuestion {
print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"

相反,英語中的LATIN CAPITAL LETTER A(U+0041系吩,或者A)不等于俄語中的CYRILLIC CAPITAL LETTER A(U+0410来庭,或者A)。兩個字符看著是一樣的穿挨,但卻有不同的語言意義:

let latinCapitalLetterA: Character = "\\u{41}"
let cyrillicCapitalLetterA: Character = "\\u{0410}"
if latinCapitalLetterA != cyrillicCapitalLetterA {
print("These two characters are not equivalent.")
}
// Prints "These two characters are not equivalent."
    • 15.2 前綴/后綴相等

通過調(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"
]

前綴 hasPrefix(_:),如下統(tǒng)計由Act 1開頭的字符串

var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
act1SceneCount += 1
}
}
print("There are \\(act1SceneCount) scenes in Act 1")
// Prints "There are 5 scenes in Act 1"

后綴 hasSuffix(_:),如下統(tǒng)計由Capulet's mansion結(jié)尾的字符串

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")
// Prints "6 mansion scenes; 2 cell scenes"
  • 16 .字符串的 Unicode 表示形式

UTF-8 : 通過遍歷String的utf8屬性來訪問它的UTF-8表示
UTF-16 : 通過遍歷String的utf16屬性來訪問它的UTF-16表示

UTF-32: 遍歷String值的unicodeScalars屬性來訪問它的 Unicode 標量表示

let dogString = "Dog"
//UTF-8
for codeUnit in dogString.utf8 {
print("\\(codeUnit) ", terminator: "")
}
print("")
//UTF-16
for codeUnit in dogString.utf16 {
print("\\(codeUnit) ", terminator: "")
}
print("")
//UTF-32
for scalar in dogString.unicodeScalars {
print("\\(scalar.value) ", terminator: "")
}
print("")

Character | UTF-8 Code Unit | UTF-16 Code Unit |UTF-32 Code Unit |Position
----|------|----|----|----|---
D(U+0044) | 68|68|68|0
o(U+006F )| 111|111|111|1
g(U+0067)| 103|103|103|2

還是直接上圖吧帽衙,官方圖哈哈

UTF8_2x.png

UTF16_2x.png
UnicodeScalar_2x.png

以上只是一些簡單的概念說(fan)明(yi)菜皂,如有錯誤請指正,謝謝厉萝。Swift 3 學(xué)習(xí) 恍飘,后續(xù)會不斷更新。
如果你覺得我的文章對你有幫助請點喜歡哦谴垫,也可以關(guān)注我章母,每周至少一篇技術(shù)更新。
或者關(guān)注 我的專題 每周至少5篇高質(zhì)量文章收錄翩剪,多謝支持乳怎。

一起學(xué)習(xí),一起進步

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末前弯,一起剝皮案震驚了整個濱河市蚪缀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恕出,老刑警劉巖椿胯,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剃根,居然都是意外死亡哩盲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門狈醉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廉油,“玉大人,你說我怎么就攤上這事苗傅∈阆撸” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵渣慕,是天一觀的道長嘶炭。 經(jīng)常有香客問我,道長逊桦,這世上最難降的妖魔是什么眨猎? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮强经,結(jié)果婚禮上睡陪,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好兰迫,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布信殊。 她就那樣靜靜地躺著,像睡著了一般汁果。 火紅的嫁衣襯著肌膚如雪涡拘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天据德,我揣著相機與錄音鲸伴,去河邊找鬼。 笑死晋控,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的姓赤。 我是一名探鬼主播赡译,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼不铆!你這毒婦竟也來了蝌焚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤誓斥,失蹤者是張志新(化名)和其女友劉穎只洒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劳坑,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了这揣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穗酥。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖框仔,靈堂內(nèi)的尸體忽然破棺而出舀武,到底是詐尸還是另有隱情,我是刑警寧澤离斩,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布银舱,位于F島的核電站,受9級特大地震影響跛梗,放射性物質(zhì)發(fā)生泄漏寻馏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一核偿、第九天 我趴在偏房一處隱蔽的房頂上張望操软。 院中可真熱鬧,春花似錦宪祥、人聲如沸聂薪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藏澳。三九已至仁锯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翔悠,已是汗流浹背业崖。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蓄愁,地道東北人双炕。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像撮抓,于是被迫代替她去往敵國和親妇斤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容