Swift的字符串類型與Foundation的NSString類連接。Foundation還擴(kuò)展了字符串來公開由NSString定義的方法谴忧。這意味著碴萧,如果您導(dǎo)入Foundation柒昏,您可以在字符串中訪問這些NSString方法,而不需要進(jìn)行強(qiáng)制轉(zhuǎn)換。
單行字符串
let someString = "Some stirng"
多行文本
多行文本使用 """ 內(nèi)容 """
沒錯(cuò)茬故,就是三個(gè)引號(hào)開頭盖灸,三個(gè)引號(hào)結(jié)尾。
多行字符串文字包含了它的起始引號(hào)和結(jié)束引號(hào)之間的所有行
let lyric = """
那是你的眼神磺芭,明亮又美麗
啊啊啊~~~
"""
print(lyric)
結(jié)果:
那是你的眼神赁炎,明亮又美麗
啊啊啊~~~
好吧,這個(gè)我一開始以為只是在格式上可以寫成多行钾腺,沒想到結(jié)果就是多行徙垫,效果等同于\n,而且這樣寫法更加方便。
還有就是當(dāng)我們想在多行文本中想控制某行不換行放棒,可以選擇在某行的末尾寫上 \ 那么下一行就不會(huì)換行了
let lyric = """
那是你的眼神姻报,明亮又美麗\
啊啊啊~~~
"""
結(jié)果:
那是你的眼神,明亮又美麗啊啊啊~~~
在多行文本中间螟,我們可以在結(jié)束引號(hào)的前面設(shè)定空格吴旋,來限定整段文本的縮進(jìn):
let lyric = """
那是你的眼神,明亮又美麗
啊啊啊~~~
"""
上面例子中,我們?cè)谧詈?""前設(shè)定了2個(gè)空格,那么之前的文本必須都是縮進(jìn)2個(gè)空格如果你這樣寫:
let lyric = """
那是你的眼神厢破,明亮又美麗
啊啊啊~~~
"""
你會(huì)發(fā)現(xiàn)會(huì)報(bào)錯(cuò)Insufficient indentation of line in multi-line string literal 多行字符串文字的行縮不足
字符串中特殊字符
\(反斜杠)
let test = "====\\===="
結(jié)果:
====\====
\t(水平選項(xiàng)卡)
let test = "\t1\t2\t3"
結(jié)果:
1 2 3
\n(換行符)
let test = "\n1\n2\n3"
結(jié)果:
1
2
3
\r(回車)
let test = "\r1\r2\r3"
結(jié)果:
1
2
3
從結(jié)果來看,\r和\n似乎沒有區(qū)別,但既然存在即表示肯定是有區(qū)別的
'\r'是回車荣瑟,\r 使光標(biāo)到行首. '\n'是換行,\n 使光標(biāo)下移一格,通常敲一個(gè)回車鍵摩泪,即是回車笆焰,又是換行(\r\n)。Unix中每行結(jié)尾只有“<換行>”见坑,即“\n”嚷掠;Windows中每行結(jié)尾是“<換行><回車>”,即“\n\r”鳄梅;Mac中每行結(jié)尾是“<回車>”
一般遇到的情況是在解析Json字符串,網(wǎng)頁數(shù)據(jù),文件信息的時(shí)候會(huì)出現(xiàn)不同的應(yīng)對(duì).
"(雙引號(hào))
let test = "\"認(rèn)識(shí)自己的無知是認(rèn)識(shí)世界的最可靠的方法叠国∥撮荩——《隨筆集》\""
結(jié)果:
"認(rèn)識(shí)自己的無知是認(rèn)識(shí)世界的最可靠的方法戴尸。——《隨筆集》"
'(單引號(hào))
let test = "\'曦\'"
結(jié)果:
'曦'
Unicode 字符就直接采用官網(wǎng)的了
let dollarSign = "\u{24}" // $, Unicode scalar U+0024
let blackHeart = "\u{2665}" // ?, Unicode scalar U+2665
let sparklingHeart = "\u{1F496}" // ??, Unicode scalar U+1F496
結(jié)果:
$ ? ??
空字符串
我們來看一下如果定義一個(gè)空字符串:
var emptyString = ""
或者
var emptyString = String()
判斷字符串是否為空:
isEmpty 方法
var emptyString = ""
if emptyString.isEmpty {
print("emptyStirng is empty")
}
字符串可變性
var variableString = "Horse"
variableString += " and carriage"
結(jié)果:
variableStrin:Horse and carriage
let constantString = "Highlander"
constantString += " and another Highlander"
發(fā)生錯(cuò)誤冤狡。
Left side of mutating operator isn't mutable: 'constantString' is a 'let' constant
變異操作符的左側(cè)是不可改變的:“常量字符串”是一個(gè)“l(fā)et”常量
簡(jiǎn)單來說就是variableString 是變量,可以通過+操作符來追加字符串, constantString 為常量,不可修改孙蒙。
這個(gè)我不得不吐槽一下,官網(wǎng)的這個(gè)解釋,不就是常量不可修改嘛,說什么可變性。
字符串是值類型
If you create a new String value, that String value is copied when it’s passed to a function or method, or when it’s assigned to a constant or variable. In each case, a new copy of the existing String value is created, and the new copy is passed or assigned, not the original version.
如果您創(chuàng)建一個(gè)新的字符串值悲雳,那么當(dāng)它傳遞給一個(gè)函數(shù)或方法時(shí)挎峦,或者當(dāng)它被分配給一個(gè)常量或變量時(shí),該字符串值將被復(fù)制。
在不同情況下合瓢,都會(huì)創(chuàng)建一個(gè)現(xiàn)有字符串值的新副本坦胶,并分配新副本,而不是原始版本。
Swift’s copy-by-default String behavior ensures that when a function or method passes you a String value, it’s clear that you own that exact String value, regardless of where it came from. You can be confident that the string you are passed won’t be modified unless you modify it yourself.
Swift的 copy-by-default 行為可以確保當(dāng)函數(shù)或方法傳遞給你一個(gè)字符串值時(shí)顿苇,不管它是從哪里來的峭咒,你都能清楚地知道你的值是什么。您可以確信纪岁,您所傳遞的字符串不會(huì)被修改凑队,除非您自己修改它。
Behind the scenes, Swift’s compiler optimizes string usage so that actual copying takes place only when absolutely necessary. This means you always get great performance when working with strings as value types.
在后臺(tái),Swift的編譯器優(yōu)化了字符串的使用幔翰,所以只有在絕對(duì)必要的情況下才會(huì)進(jìn)行實(shí)際的復(fù)制漩氨。這意味著在使用字符串作為值類型時(shí),您總是獲得很好的性能遗增。
這個(gè)就有別于OC了叫惊,OC中有明確的分為NSString(不可變)和NSMutableString(可變),swift中只有這么一種了,通過對(duì)此的優(yōu)化更加確保了數(shù)據(jù)的安全贡定。
字符
定義一個(gè)字符(Character)類型的常量charA
let charA:Character = "A"
print("charA:\(charA)")
結(jié)果:
charA:A
您可以通過使用for循環(huán)遍歷字符串來訪問字符串的單個(gè)字符值:
let character = ""
let str = "窗外的麻雀"
for character in str {
print(character)
}
結(jié)果:
窗
外
的
麻
雀
創(chuàng)建一個(gè)字符值數(shù)組:
let catCharacters: [Character] = ["C", "a", "t", "!", "??"]
print(catCharacters)
結(jié)果:
["C", "a", "t", "!", "??"]
可以通過String(字符數(shù)組)
來將字符數(shù)組轉(zhuǎn)換成字符串
let catCharacters: [Character] = ["C", "a", "t", "!", "??"]
let catString = String(catCharacters)
print(catString)
結(jié)果:
Cat!??
字符串的連接:
我們可以用 +
操作符連接字符串
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
print("welcome \(welcome)")
結(jié)果:
welcome hello there
除了+
操作符之外,還有append方法
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
print("welcome \(welcome)")
結(jié)果:
welcome hello there!
append是將字符串追加到原本字符串的末尾
以上的添加方法是通過連接兩個(gè)字符串的值形成一個(gè)新的值
而在有的時(shí)候我們其實(shí)只需要臨時(shí)的展示而已涂召,不需要去改變?cè)械闹?那么這個(gè)時(shí)候其實(shí)只需要這樣做就可以了:
let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
print(badStart)
結(jié)果:
one
twothree
one
two
可以看到我們?cè)谳敵鰌rint中將其相加,雖然顯示了床佳,但其實(shí)badStart的結(jié)果并沒有改變。
字符串的插值
在使用字符串的時(shí)候,我們可能需要利用其它的變量來改變我們目前的數(shù)據(jù),而這個(gè)時(shí)候我們可以使用 \(value)
來將我們需要的值
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
結(jié)果:
3 times 2.5 is 7.5
當(dāng)然了躯嫉,這個(gè)也不是萬能,它是不能將未轉(zhuǎn)義的\
直接放置于()
中的:
錯(cuò)誤的方式
let message = "\(\)"
print(message)
let message = "\(\')"
print(message)
正確的方式是這樣的:
let message = "\("\'")"
print(message)
結(jié)果:
'
計(jì)算字符的個(gè)數(shù)
計(jì)算字符的個(gè)數(shù)是我們比較常用的方法count
let unusualMenagerie = "Koala ??, Snail ??, Penguin ??, Dromedary ??"
print("unusualMenagerie has \(unusualMenagerie.count) characters")
結(jié)果:
unusualMenagerie has 40 characters
當(dāng)然了,count并不總是能夠計(jì)算清楚我們的字符個(gè)數(shù):
var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
這個(gè)計(jì)算結(jié)果是4
word += "\u{301}"
print("the number of characters in \(word) is \(word.count)")
當(dāng)我們計(jì)算的會(huì)發(fā)現(xiàn)結(jié)果仍然是4
這是為什么呢?
因?yàn)閟wift中的字符串運(yùn)用了擴(kuò)展字元簇(Extended Grapheme Clusters)
擴(kuò)展字元簇可以由多個(gè)Unicode標(biāo)量組成尤泽。
這意味著不同的字符和相同字符的不同表示可以要求不同的內(nèi)存數(shù)量來存儲(chǔ)脆淹。
因此,Swift中的字符不會(huì)在字符串的表示中占用相同數(shù)量的內(nèi)存瘫镇。
結(jié)果鼎兽,字符串中的字符數(shù)無法計(jì)算.
如果您使用的是特別長(zhǎng)的字符串值,請(qǐng)注意铣除,count屬性必須遍歷整個(gè)字符串中的Unicode標(biāo)量谚咬,以便確定該字符串的字符。
比如:字母é可以是一個(gè)單獨(dú)的Unicode scalar:U+00E9尚粘,也可以是多個(gè)純量的組合:U+0065U+0301 (其中U+0065就是字母e)择卦。在Swift中,這兩種情況都認(rèn)為是一個(gè)字符郎嫁,因此獲取字符串長(zhǎng)度的時(shí)候(用全局函數(shù)count())秉继,返回的值是相同的,這意味著字符串的改變并不一定意味著其長(zhǎng)度發(fā)生變化泽铛。
count屬性返回的字符數(shù)并不總是與包含相同字符的NSString的長(zhǎng)度屬性相同尚辑。
NSString的length是基于字符串的utf-16表示的16位代碼單元的數(shù)量,而不是字符串中Unicode擴(kuò)展的grapheme集群的數(shù)量
字符串索引
let greeting = "Guten Tag!"
//字符串中的開頭字母
print(greeting[greeting.startIndex])
//index()表示獲取字符串中某個(gè)下標(biāo)的元素,before意味著獲取最后一位的之前的下標(biāo)
//endIndex表示字符串最后一位
print(greeting[greeting.index(before: greeting.endIndex)])
//after表示獲取某個(gè)下標(biāo)之后
print(greeting[greeting.index(after: greeting.startIndex)])
//這個(gè)方法表示以startIndex下標(biāo)開始盔腔,偏移7位
let index = greeting.index(greeting.startIndex, offsetBy: 7)
print(greeting[index])
結(jié)果:
G
!
u
a
使用索引屬性來訪問字符串中各個(gè)字符的所有索引:
for index in greeting.indices {
print("\(greeting[index]) ", terminator: "")
}
結(jié)果:
G u t e n T a g !
這里的terminator是print方法中參數(shù),默認(rèn)是添加換行符\n
let greeting = "Guten Tag!"
for index in greeting.indices {
print("\(greeting[index]) ", terminator: "\n")
}
G
u
t
e
n
T
a
g
!
感覺跟print沒有區(qū)別吧杠茬。
let greeting = "Guten Tag!"
for index in greeting.indices {
print("\(greeting[index]) ", terminator: "1")
}
結(jié)果:
G 1u 1t 1e 1n 1 1T 1a 1g 1! 1
這個(gè)其實(shí)就是在每次獲取單個(gè)字符之后添加一個(gè)字符月褥。
字符串的插入和刪除
插入
insert(value,at:index)
var welcome = "hello"
welcome.insert("!", at:welcome.endIndex)
print(welcome)
結(jié)果:
hello!
var welcome = "hello!"
welcome.insert(contentsOf: " world", at: welcome.index(before: welcome.endIndex))
print(welcome)
結(jié)果:
hello world!
移除
remove(at:index)
根據(jù)下標(biāo)進(jìn)行移除
removeSubrange
根據(jù)提供的范圍進(jìn)行移除
var welcome = "hello!"
welcome.remove(at: welcome.index(before: welcome.endIndex))
print(welcome)
結(jié)果:
hello
var welcome = "hello world"
//空格的位置 - 末尾
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
print(welcome)
結(jié)果:
hello
后續(xù)更新,敬請(qǐng)期待...