Swift 001-字符串 官方文檔 概述

基于Swift 版本 5.1

// 一個(gè)Unicode字符串值心软,它是字符的集合娩怎。
struct String

字符串是一系列字符組成的集合爆阶,如“Swift”沃测。Swift中的字符串是Unicode正確且對(duì)語(yǔ)言環(huán)境不敏感的斥扛,旨在提高效率入问。字符串類型與Objective-C類NSString連接,并提供與處理字符串的C函數(shù)的互操作性稀颁。
您可以使用字符串文字或字符串內(nèi)插來(lái)創(chuàng)建新字符串芬失。字符串文字是用引號(hào)括起來(lái)的一系列字符。
Swift的String類型是一種值類型,String值再傳遞給方法或者函數(shù)的時(shí)候,會(huì)被復(fù)制過(guò)去,還有賦值給常量或者變量的時(shí)候也一樣匾灶。每一次賦值和傳遞,現(xiàn)存的String值都會(huì)被復(fù)制一次,傳遞走的是拷貝而不是原本棱烂。Swift編譯器優(yōu)化了字符串使用的資源,實(shí)際上拷貝只會(huì)再確實(shí)需要的時(shí)候才進(jìn)行。
字符串插值是字符串文字阶女,用于評(píng)估所有包含的表達(dá)式并將結(jié)果轉(zhuǎn)換為字符串形式颊糜。字符串插值為您提供了一種由多個(gè)片段構(gòu)建字符串的簡(jiǎn)便方法。將每個(gè)表達(dá)式括在括號(hào)內(nèi)的字符串內(nèi)插中秃踩,并以反斜杠為前綴衬鱼。

let name = "Rosa"
let personalizedGreeting = "Welcome, \(name)!"
// personalizedGreeting == "Welcome, Rosa!"

let price = 2
let number = 3
let cookiePrice = "\(number) cookies: $\(price * number)."
// cookiePrice == "3 cookies: $6."

使用串聯(lián)運(yùn)算符(+)合并字符串。

let longerGreeting = greeting + " We're glad you're here!"
// longerGreeting == "Welcome! We're glad you're here!"

多行字符串文字用三個(gè)雙引號(hào)(""")括起來(lái)憔杨,每個(gè)定界符在其自己的行上鸟赫。縮進(jìn)從多行字符串文字的每一行中去除消别,以匹配結(jié)束定界符的縮進(jìn)抛蚤。

let banner = """
a\
b
c
d
"""
print(banner)
// log
/*
  ab
  c
  d
*/
修改和比較字符串

字符串始終具有值語(yǔ)義。修改字符串的副本不會(huì)影響原始字符串寻狂。

var otherGreeting = greeting
otherGreeting += " Have a nice time!"
// otherGreeting == "Welcome! Have a nice time!"

print(greeting)
// Prints "Welcome!"

使用Unicode規(guī)范表示來(lái)使用等于運(yùn)算符(==)或關(guān)系運(yùn)算符(如<或>=)比較字符串是否相等岁经。結(jié)果,字符串的不同表示形式比較相等蛇券。

let cafe1 = "Cafe\u{301}"
let cafe2 = "Café"
print(cafe1 == cafe2)
// Prints "true"

Unicode標(biāo)量值"\u{301}"修改前面的字符以包含重音符號(hào)蒿偎,因此"e\u{301}"具有與單個(gè)Unicode標(biāo)量值相同的規(guī)范表示形式"é"。
基本的字符串操作對(duì)語(yǔ)言環(huán)境設(shè)置不敏感怀读,可確保字符串比較和其他操作始終具有單個(gè)穩(wěn)定的結(jié)果诉位,從而允許將字符串用作Dictionary實(shí)例中的鍵或用于其他目的。

訪問(wèn)字符串元素

字符串是擴(kuò)展的字素簇的集合菜枷,這些簇近似于人類可讀的字符苍糠。許多單獨(dú)的字符(例如“é”,“?”和“????”)可以由多個(gè)Unicode標(biāo)量值組成啤誊。這些標(biāo)量值由Unicode的邊界算法組合成擴(kuò)展的字形簇岳瞭,由Swift Character類型表示拥娄。字符串的每個(gè)元素都由一個(gè)Character實(shí)例表示。
例如瞳筏,要檢索較長(zhǎng)字符串的第一個(gè)單詞稚瘾,可以搜索一個(gè)空格,然后從該字符串的前綴創(chuàng)建一個(gè)子字符串姚炕,直到該點(diǎn)為止:

let name = "Marie Curie"
let firstSpace = name.firstIndex(of: " ") ?? name.endIndex
let firstName = name[..<firstSpace]
// firstName == "Marie"

該常數(shù)是實(shí)例摊欠,表示一個(gè)字符串的子串,同時(shí)共享原始字符串的存儲(chǔ)類型柱宦,一種類型些椒。子字符串與字符串具有相同的接口。

print("\(name)'s first name has \(firstName.count) letters.")
// Prints "Marie Curie's first name has 5 letters."
訪問(wèn)字符串的Unicode表示形式

如果你需要在不同的Unicode編碼掸刊,字符串的使用一個(gè)編碼訪問(wèn)字符串的內(nèi)容免糕,或性質(zhì)。每個(gè)屬性都以一系列代碼單元的形式提供對(duì)字符串視圖的訪問(wèn)忧侧,每個(gè)代碼單元均以不同的Unicode編碼進(jìn)行編碼石窑。unicodeScalars、utf16蚓炬、utf8
為了演示每個(gè)字符串可用的不同視圖松逊,以下示例使用此String實(shí)例:

let cafe = "Cafe\u{301} du ??"
print(cafe)
// Prints "Café du ??"

該cafe字符串是九個(gè)字符顯示的字符串時(shí)可見(jiàn)的集合。

print(cafe.count)
// Prints "9"
print(Array(cafe))
// Prints "["C", "a", "f", "é", " ", "d", "u", " ", "??"]"
Unicode標(biāo)量視圖

字符串的unicodeScalars屬性是Unicode標(biāo)量值的集合试吁,21位代碼是Unicode的基本單位。每個(gè)標(biāo)量值都用Unicode表示楼咳。標(biāo)量實(shí)例熄捍,相當(dāng)于一個(gè)UTF-32代碼單元。

print(cafe.unicodeScalars.count)
// Prints "10"
print(Array(cafe.unicodeScalars))
// Prints "["C", "a", "f", "e", "\u{0301}", " ", "d", "u", " ", "\u{0001F30D}"]"
print(cafe.unicodeScalars.map { $0.value })
// Prints "[67, 97, 102, 101, 769, 32, 100, 117, 32, 127757]"

unicodeScalars視圖的元素包含cafe字符串中的每個(gè)Unicode標(biāo)量值母怜。特別是余耽,因?yàn)閏afe是使用“é”字符的分解形式聲明的,所以u(píng)nicodeScalars包含字母“e”(101)和重音字符“’”(769)的標(biāo)量值苹熏。

UTF-16視圖

字符串的utf16屬性是UTF-16編碼單元的集合碟贾,這是字符串的Unicode標(biāo)量值的16位編碼形式。每個(gè)代碼單元存儲(chǔ)為UInt16實(shí)例轨域。

print(cafe.utf16.count)
// Prints "11"
print(Array(cafe.utf16))
// Prints "[67, 97, 102, 101, 769, 32, 100, 117, 32, 55356, 57101]"

utf16視圖的元素是UTF-16編碼時(shí)字符串的代碼單元袱耽。這些元素與通過(guò)索引的NSString api訪問(wèn)的元素相匹配。

let nscafe = cafe as NSString
print(nscafe.length)
// Prints "11"
print(nscafe.character(at: 3))
// Prints "101"
UTF-8視圖

字符串的utf8屬性是UTF-8代碼單元的集合干发,這是字符串的Unicode標(biāo)量值的8位編碼形式朱巨。每個(gè)代碼單元存儲(chǔ)為一個(gè)UInt8實(shí)例。

print(cafe.utf8.count)
// Prints "14"
print(Array(cafe.utf8))
// Prints "[67, 97, 102, 101, 204, 129, 32, 100, 117, 32, 240, 159, 140, 141]"

utf8視圖的元素是UTF-8編碼時(shí)字符串的代碼單元枉长。此表示與將字符串實(shí)例傳遞給C api時(shí)使用的表示相匹配冀续。

let cLength = strlen(cafe)
print(cLength)
// Prints "14"
測(cè)量字符串長(zhǎng)度

當(dāng)您需要知道一個(gè)字符串的長(zhǎng)度時(shí)琼讽,您必須首先考慮將該長(zhǎng)度用于什么。您是在度量將顯示在屏幕上的字符數(shù)洪唐,還是在度量特定編碼中字符串所需的存儲(chǔ)空間?當(dāng)通過(guò)不同的視圖測(cè)量時(shí)钻蹬,一個(gè)字符串的長(zhǎng)度可能會(huì)有很大的差異。
例如凭需,像大寫字母A這樣的ASCII字符由它的四個(gè)視圖中的每個(gè)元素表示问欠。A的Unicode標(biāo)量值是65,它足夠小功炮,可以同時(shí)容納UTF-16和UTF-8中的單個(gè)代碼單元溅潜。

let capitalA = "A"
print(capitalA.count)
// Prints "1"
print(capitalA.unicodeScalars.count)
// Prints "1"
print(capitalA.utf16.count)
// Prints "1"
print(capitalA.utf8.count)
// Prints "1"

另一方面,表情符號(hào)標(biāo)志字符由一對(duì)Unicode標(biāo)量值(如"\u{1F1F5}"和)構(gòu)成"\u{1F1F7}"薪伏。這些標(biāo)量值中的每一個(gè)都太大滚澜,以致無(wú)法放入單個(gè)UTF-16或UTF-8代碼單元中。結(jié)果嫁怀,字符串的每個(gè)視圖"????"報(bào)告的長(zhǎng)度都不同设捐。

let flag = "????"
print(flag.count)
// Prints "1"
print(flag.unicodeScalars.count)
// Prints "2"
print(flag.utf16.count)
// Prints "4"
print(flag.utf8.count)
// Prints "8"

要檢查字符串是否為空,請(qǐng)使用其isEmpty屬性塘淑,而不是將其中一個(gè)視圖的長(zhǎng)度與0進(jìn)行比較萝招。與isEmpty不同,計(jì)算視圖的count屬性需要遍歷字符串的元素存捺。

訪問(wèn)字符串視圖元素

要查找字符串的各個(gè)元素槐沼,請(qǐng)為任務(wù)使用適當(dāng)?shù)囊晥D。例如捌治,要檢索較長(zhǎng)字符串的第一個(gè)單詞岗钩,您可以搜索該字符串的空格,然后從該字符串的前綴到該點(diǎn)創(chuàng)建一個(gè)新字符串肖油。

let name = "Marie Curie"
let firstSpace = name.firstIndex(of: " ") ?? name.endIndex
let firstName = name[..<firstSpace]
print(firstName)
// Prints "Marie"

字符串及其視圖共享索引兼吓,因此可以使用相同的firstSpace索引訪問(wèn)名稱字符串的UTF-8視圖。

print(Array(name.utf8[..<firstSpace]))
// Prints "[77, 97, 114, 105, 101]"

注意森枪,一個(gè)視圖的索引在另一個(gè)視圖中可能沒(méi)有確切的對(duì)應(yīng)位置视搏。例如,上面聲明的標(biāo)記字符串包含一個(gè)字符县袱,但是當(dāng)編碼為UTF-8時(shí)浑娜,它由8個(gè)代碼單元組成。下面的代碼為標(biāo)記中的第一個(gè)和第二個(gè)位置創(chuàng)建常量式散。use utf8視圖棚愤。使用這些索引訪問(wèn)utf8視圖將生成第一個(gè)和第二個(gè)代碼UTF-8單元。

let firstCodeUnit = flag.startIndex
let secondCodeUnit = flag.utf8.index(after: firstCodeUnit)
// flag.utf8[firstCodeUnit] == 240
// flag.utf8[secondCodeUnit] == 159

但是,當(dāng)用來(lái)訪問(wèn)標(biāo)記字符串本身的元素時(shí)宛畦,secondCodeUnit索引并不對(duì)應(yīng)于特定字符的位置瘸洛。不是只訪問(wèn)特定的UTF-8代碼單元,而是將該索引視為字符在索引編碼偏移處的位置次和。在secondCodeUnit的情況下反肋,該字符仍然是標(biāo)記本身。
如果需要驗(yàn)證一個(gè)字符串視圖中的索引是否與另一個(gè)視圖中的確切位置相對(duì)應(yīng)踏施,請(qǐng)使用索引的samePosition(in:)方法或init(_:within:)初始化器石蔗。

if let exactIndex = secondCodeUnit.samePosition(in: flag) {
    print(flag[exactIndex])
} else {
    print("No exact match for this position.")
}
// Prints "No exact match for this position."
性能優(yōu)化

盡管Swift中的字符串具有值語(yǔ)義,但字符串使用寫時(shí)復(fù)制策略將數(shù)據(jù)存儲(chǔ)在緩沖區(qū)中畅形。然后养距,這個(gè)緩沖區(qū)可以由字符串的不同副本共享。一個(gè)字符串的數(shù)據(jù)只有在多個(gè)字符串實(shí)例使用同一個(gè)緩沖區(qū)時(shí)日熬,才會(huì)在發(fā)生變化時(shí)惰性地復(fù)制棍厌。因此,任何順序的第一個(gè)突變操作可能會(huì)花費(fèi)O(n)時(shí)間和空間竖席。
當(dāng)字符串的連續(xù)存儲(chǔ)被填滿時(shí)耘纱,必須分配一個(gè)新的緩沖區(qū),并且必須將數(shù)據(jù)移動(dòng)到新的存儲(chǔ)中毕荐。字符串緩沖區(qū)使用指數(shù)增長(zhǎng)策略束析,當(dāng)對(duì)多個(gè)附加操作求平均值時(shí),該策略使附加到字符串成為常數(shù)時(shí)間操作憎亚。

字符串和NSString之間的橋接

任何字符串實(shí)例都可以使用類型轉(zhuǎn)換操作符(as)橋接到NSString员寇,而來(lái)自O(shè)bjective-C的任何字符串實(shí)例都可以使用NSString實(shí)例作為其存儲(chǔ)。因?yàn)镹SString的任意子類都可以成為一個(gè)字符串實(shí)例第美,所以當(dāng)一個(gè)字符串實(shí)例由NSString存儲(chǔ)支持時(shí)蝶锋,不能保證它的表示形式或效率。因?yàn)镹SString是不可變的斋日,它就像存儲(chǔ)被一個(gè)拷貝共享一樣牲览。任何序列中的第一個(gè)操作都會(huì)導(dǎo)致元素被復(fù)制到唯一的墓陈、連續(xù)的存儲(chǔ)中恶守,這可能會(huì)消耗O(n)時(shí)間和空間,其中n是字符串的編碼表示長(zhǎng)度(或者更多贡必,如果底層NSString具有不尋常的性能特征)兔港。
有關(guān)本討論中使用的Unicode術(shù)語(yǔ)的更多信息,請(qǐng)參見(jiàn)Unicode.org詞匯表仔拟。特別是衫樊,本文討論了擴(kuò)展的grapheme集群、Unicode標(biāo)量值和規(guī)范等價(jià)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末科侈,一起剝皮案震驚了整個(gè)濱河市载佳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌臀栈,老刑警劉巖蔫慧,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異权薯,居然都是意外死亡姑躲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門盟蚣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)黍析,“玉大人,你說(shuō)我怎么就攤上這事屎开〔妫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵牍戚,是天一觀的道長(zhǎng)侮繁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)如孝,這世上最難降的妖魔是什么宪哩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮第晰,結(jié)果婚禮上锁孟,老公的妹妹穿的比我還像新娘。我一直安慰自己茁瘦,他們只是感情好品抽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著甜熔,像睡著了一般圆恤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腔稀,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天盆昙,我揣著相機(jī)與錄音,去河邊找鬼焊虏。 笑死淡喜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诵闭。 我是一名探鬼主播炼团,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼澎嚣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瘟芝?” 一聲冷哼從身側(cè)響起易桃,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锌俱,沒(méi)想到半個(gè)月后颈抚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嚼鹉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年贩汉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锚赤。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡匹舞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出线脚,到底是詐尸還是另有隱情赐稽,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布浑侥,位于F島的核電站姊舵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寓落。R本人自食惡果不足惜括丁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伶选。 院中可真熱鬧史飞,春花似錦、人聲如沸仰税。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)陨簇。三九已至吐绵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間河绽,已是汗流浹背己单。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留葵姥,地道東北人荷鼠。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓句携,卻偏偏與公主長(zhǎng)得像榔幸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • Swift學(xué)習(xí)有問(wèn)必答群 : 313838956 ( mac版QQ有權(quán)限要求, 入群只能通過(guò)手機(jī)版 QQ申請(qǐng)...
    Guards翻譯組閱讀 6,605評(píng)論 9 13
  • 級(jí)別: ★☆☆☆☆標(biāo)簽:「iOS」「Swift 5.1」「字符串」作者: 沐靈洛審校: QiShare團(tuán)隊(duì) 字符串...
    QiShare閱讀 4,134評(píng)論 0 11
  • 字符串字符串是一系列字符組成的削咆。Swift字符串由String類型表示牍疏。1.使用字符串文字作為常量或變量的初始值:...
    沐靈洛閱讀 785評(píng)論 0 5
  • String是例如"hello, world","albatross"這樣的有序的Character(字符)類型的...
    窮人家的孩紙閱讀 852評(píng)論 2 1
  • 悼涼山救火英雄而作 四月花殤風(fēng)寥落拨齐,飄飄灑灑作泥塵鳞陨。 問(wèn)風(fēng)何故摧花急?未待春完便葬春瞻惋。
    上元鴻舍主人閱讀 682評(píng)論 7 25