字符串和字符
Swift的 String 类型是一种快速、现代的字符串实现,每个字符串由独立于编码的Unicode字符组成,并支持在各种Unicode表示中访问这些字符。
注意
Swift的 String 类型与Foundation的 NSString 类型桥接。Foundation框架扩展了 String 以公开了 NSString 的方法,这意味着,只要导入Foundation框架,不用转换就可以直接访问 String 的 NSString 方法。
<br />
字符串字面量
字符串字面量用来初始化 String 类型的常量或变量:
let someString = "Some string literal value"
多行字符串字面量
多行字符串字面量使用三对双引号表示:
let quotation = """
The White Rabbit put on his spectacles. "Where shall I begin,
please your Majesty?" he asked.
"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""
多行字符串字面量包括其开头和结尾引号之间的所有行。 字符串从开头引号(“”“)之后的第一行开始,并在结束引号之前的行结束,这意味着以下两个字符串都不会以换行符开头或结尾:
let singleLineString = "These are the same."
let multilineString = """
These are the same.
"""
可在多行字符串字面量中使用换行符表示换行。若仅仅只想在代码中使用换行提高字符串可读性,而不想让字符串的值包含该还行符,可在该行末尾加入反斜杠( \ ):
let softWrappedQuotation = """
The White Rabbit put on his spectacles. "Where shall I begin, \
please your Majesty?" he asked.
"Begin at the beginning," the King said gravely, "and go on \
till you come to the end; then stop."
"""
可在开头或结尾加入空白行表示多行字符串值的开头和结尾为空行:
let lineBreaks = """
This string starts with a line break.
It also ends with a line break.
"""
字符串字面量中的特殊字符
字符串字面量可包含以下特殊字符:
- 转义字符:\0 (空字符)、\\ (反斜杠)、\t (水平缩进)、\n (换行符)、\r (回车)、\" (双引号)、\' (单引号)
- 任意Unicode标量:\u{n},n为1-8位16进制数,该值等于有效的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
在多行字符串字面量中使用一个双引号而不需要转义,当需要使用三个双引号时,请转义其中至少一个双引号:
let threeDoubleQuotes = """
Escaping the first quote \"""
Escaping all three quotes \"\"\"
"""
<br />
初始化空字符串
使用空字符串字面量或使用初始化语法新建一个 String 实例来初始化空字符串:
var emptyString = "" // empty string literal
var anotherEmptyString = String() // initializer syntax
判断字符串是否为空使用其isEmpty属性:
if emptyString.isEmpty {
print("Nothing to see here")
}
<br />
可变字符串
将String声明为变量(var)则为可变字符串(增删改查),声明为常量(let)则为不可变字符串(不可修改):
var variableString = "Horse"
variableString += " and carriage"
// variableString 等于 "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// 抛出编译错误 - a constant string cannot be modified
<br />
字符串是值类型
与Objective-C不同,Swift的String是值类型。
若创建一个新的String值,那么当它传递给一个函数或者方法,或者当它被赋值给一个常量或者变量时,这个String值被复制。 在每种情况下,将创建现有String值的新副本,并且新副本将被传递或分配,而不是原始版本。
<br />
使用字符
遍历字符串获取各个Character值:
for character in "Dog!🐶" {
print(character)
}
// D
// o
// g
// !
// 🐶
使用Character类型标注创建单个字符:
let exclamationMark: Character = "!"
Character数组可传入字符串初始化器初始化一个String值:
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// 打印 "Cat!🐱"
<br />
连接字符串和字符
多个String值可通过+操作符连接创建一个新String值:
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome 等于 "hello there"
使用+=操作符将新String值追加到当前String值中:
var instruction = "look over"
instruction += string2
// instruction 等于 "look over there"
String类型的append()方法可将Character值追加到String中:
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome 等于 "hello there!"
<br />
字符串插值
字符串插值是将任意类型的值包含在字符串字面量中,并产生一个新的String值:
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
<br />
Unicode
Swift的字符串和字符类型完全兼容Unicode。
Unicode标量
Swift的String类型由Unicode标量构建。
Unicode标量是U + 0000到U + D7FF(包括U + E000到U + 10FFFF)之间的任何Unicode代码点。 Unicode标量不包括Unicode代理对代码点,它们是U + D800到U + DFFF范围内的代码点。
扩展的格式化集群
扩展的图形集合是将许多复杂的脚本字符表示为单个字符值的灵活方式。 例如,来自韩文字母表的韩文字母可以表示为预先设置的或分解的序列。
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e followed by ́
// eAcute is é, combinedEAcute is é
这两个表示符合Swift中的单个字符值:
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed is 한, decomposed is 한
<br />
获取和修改字符串
通过字符串的方法、属性或下标语法可获取和修改一个字符串。
字符串切片
每个String值都具有相关联的索引类型String.Index,它与字符串中每个Character的位置相对应。
使用startIndex属性访问字符串的第一个字符的位置。endIndex属性是字符串中最后一个字符后面的位置。因此,endIndex属性不是字符串下标的有效参数。若String为空,则startIndex和endIndex相等。
使用下标语法获取String索引的字符:
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
视图访问字符串范围外的索引或索引外的字符或抛出运行时错误:
greeting[greeting.endIndex] // Error
greeting.index(after: greeting.endIndex) // Error
使用indices属性获取字符串的所有索引,用于迭代:
for index in greeting.indices {
print("\(greeting[index]) ", terminator: "")
}
插入和删除
使用insert(_:at:)将单个字符插入到字符串的指定下标,插入另外的字符串使用insert(contentsOf:at:):
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
移除单个字符使用remove(at:)方法,移除字符串为removeSubrange(_:):
welcome.remove(at: welcome.index(before: welcome.endIndex))
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
子字符串
当从原字符串截取子串时,得到的是Substring的实例,而不是String。Substring的方法与String大致相同,但Substring只能临时使用,若想长时间存储,要将其转换为String。
let greeting = "Hello, world!"
let index = greeting.index(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"
// Convert the result to a String for long-term storage.
let newString = String(beginning)
Swift对Substring作了性能优化,Substring重用了原String的存储内存。正因如此,Substring不适合长期使用。
<br />
字符串比较
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")
}
Unicode字符串相等性:
// "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")
}
注意
Swift字符串和字符比较不区分大小写
前缀和后缀想等性
使用字符串的hasPrefix(_:)和hasSuffix(_:)判断字符串是否有特定的前缀或后缀。