引入
字符串是一系列的字符, 使用 String 类型表示。Swift的字符串类型是一种快速且标准的实现。 每个字符串都由独立于编码的 Unicode 字符组成, 并支持以各种 Unicode 表示形式访问这些字符。
字符串字面量
字符串字面量是由双引号包围的字符序列。
let name = "hzclog"
多行字符串
如果需要一个跨多行的字符串, 可以使用多行字符串字面量: 由三个双引号包围的字符序列。
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."
"""
如果在多行字符串中包含换行符, 换行符也会出现在字符串的值中。
运行结果
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.”
特殊字符
字符串中可以包含下面的特殊字符
- 转义特殊字符 \0(空字符)、 \\(反斜线)、 \t(水平制表符)、 \n(换行符)、 \r(回车符)、 \“(双引号)和 \‘(单引号)
- 写作 \u{n} 格式的Unicode字符值。
比如下面的示例:
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\u{24}" // $
let blackHeart = "\u{2665}" // ♥
let sparklingHeart = "\u{1F496}" // 💖
扩展分隔符
将字符串放在扩展分隔符中, 就可以直接包含特殊字符了, 这样不会产生特殊效果。
let wiseWords = #""Imagination is more important than knowledge" - Einstein"#
// "Imagination is more important than knowledge" - Einstein
let dollarSign = #"\u{24}"# // \u{24}
初始化空字符串
可以使用字面量或者初始化器创建字符串实例。
var emptyString = ""
var anotherEmptyString = String()
字符串的 isEmpty
属性判断字符串是否为空。
var emptyString = ""
print(emptyString.isEmpty) // true
字符串的可变性
字符串是否可变, 取决于将字符串赋值给变量还是常量。
var str1 = "hello"
str1 += "world"
print(str1) // helloworld
let str2 = "come"
str2 += "in" // 报错:'str2' is a 'let' constant
print(str2)
字符串是值类型
Swift中的字符串类型是值类型。
如果创建一个字符串值, 将其赋值给常量或者变量时, 会复制该字符串值;
学习函数以后, 如果给函数传入字符串值, 也会复制, 即创建这个字符串的副本。
这样做的好处是: 当函数传入字符串值,或者将已有字符串赋值给新变量时, 我们可以随意操作它, 而不用担心会影响原来的值。
拼接字符串(+)
上个章节我们已经见识过了,不再赘述。
字符串插值
字符串插值我们也学习过了,不过可以补充一点新内容。
let birth = 1991
// 插值输出
print("出生在:\(birth)年") // 出生在:1991年
// 想原样输出里面的文本,使用扩展分隔符
print(#"出生在:\(birth)年"#) // 出生在:\(birth)年
// 圆括号里面也不单纯只能是变量或常量,可以是一个表达式
print("年龄是:\(2024 - birth)岁") // 年龄是:33岁
字符计数
想要知道字符串中有多少个字符,可以使用 count
属性。
let message = "hello world"
print(message.count) // 11, 注意空格符也是字符
访问和修改字符串
字符串索引
每个字符串值都有关联的索引类型: String.Index
, 它与字符串中每个字符串的位置相对应。
startIndex
属性访问字符串的第一个字符的位置。 endIndex
属性是字符串最后一个字符
后面的位置。 如果字符串为空, startIndex
和 endIndex
就是相等的。
index(before:)
方法可以访问给定索引之前的索引。index(after:)
方法可以访问给定索引之后的索引。index(_:offsetBy:)
方法可以访问给定偏移位置的索引。
知道了索引以后, 可以通过语法 字符串[索引]
访问对应的字符。 用代码来瞧瞧。
let message = "hello world"
// 起始索引的字符
print(message[message.startIndex]) // h
// 起始位置之后的字符
print(message[message.index(after: message.startIndex)]) // e
// 最后一个字符
print(message[message.index(before: message.endIndex)]) // d
// 起始位置之后,偏移6个位置的字符
print(message[message.index(message.startIndex, offsetBy: 6)]) // w
访问范围以外的索引,就会触发运行错误。
let message = "hello world"
print(message[message.endIndex]) // 错误
插入和移除内容
在指定索引插入单个字符, 使用 insert(_:at:)
方法。
在指定索引插入另一个字符串内容, 使用 insert(contentsOf:at:)
方法。
var message = "hello world"
// 在字符串默认插入!
message.insert("!", at: message.endIndex)
print(message) // hello world!
let anotherMessage = "what?"
// 在字符串开头插入anotherMessage内容
message.insert(contentsOf: anotherMessage, at: message.startIndex)
print(message) // what?hello world!
要删除指定索引的单个字符, 使用 remove(at:)
方法。
要删除指定范围的子串, 使用 removeSubrange(_:)
方法。
var message = "hello hzclog!"
// 删除!
message.remove(at: message.index(before: message.endIndex))
print(message) // hello hzclog
// 创建索引范围(学习range以后,再过来看)
let range = message.index(message.endIndex, offsetBy: -7)..<message.endIndex
// 删除指定范围
message.removeSubrange(range)
print(message) // hello
子串
要从字符串中获取子串, 得到的结果是 Substring
的实例。 可以使用 String
将子串转换为字符串实例。
let message = "Hello, world!"
// firstIndex(of:) 获取给定字符在字符串的索引, 因为字符可能不存在,所以给一个后备值startIndex
let index = message.firstIndex(of: ",") ?? message.startIndex
// 通过索引范围获取子串
let beginning = message[..<index]
// 将子串转换成字符串使用
let newString = String(beginning)
print(newString) // Hello
子串的实例重复使用了原始字符串的部分内存, 这就意味着只要使用子串, 原始字符串就必须 存在于内存中。
为了子串的使用不受影响, 最好使用 String 转化新的字符串,拥有独立空间。
字符串和字符比较
Swift支持字符串和字符比较, 这种比较使用相对较少, 感兴趣可以看这里 Comparing Strings。
下一章
本章学习了字符串和字符相关的内容, 下个章节中我们学习Swift中的集合类型。