字符串的初始化
字面量
Swift字面量是 固定顺序的文本字符。Swift会将此推断为String类型。
单行字面量
可以通过双引号("") 包裹的形式创建
var emptyStr = ""
var str = "text"
多行字面量
可以通过三引号(""" """) 包裹的形式创建。
在多行字面量内 使用 换行符(回车键), 则是按照换行输出,如果仅想易读而实际不换行, 可以使用反斜杠 \ 分隔。
var linesStr = """
one line,
two lines
"""
print(linesStr)
// one line,
two lines
var linesStr = """
one line,\
two lines
"""
print(linesStr)
// one line two lines
初始化语法器
也可以通过 String() 初始化器语法创建
var emptyStr = String()
let catCharacter : [Character] = ["C","a","t","!","🐱"]
let cat = String(catCharacter) // Cat!🐱
特殊字符
转义特殊字符
\0 : 空字符, \\ : 反斜杠, \t :水平制表符, \n: 换行符, \r: 回车符, \": 双引号, \':单引号 等等
Unicode标量
\u{n}: n为 1-8 位的 16进制数字,其值为合法的Unicode值
let sparklingHeart = "\u{1F496}" //💘
多行字面量的引号
在多行字面量里, 如果是双引号 "" 无需特殊转义,即可显示, 如果是三引号 """, 则至少需要转义一个引号。
Raw String
扩展字符串分隔符: 将字符串放在 " 内, 并由 # 在最外层包裹。如果字符串内部有 #, 则首尾的 # 个数需要增多一个,首尾的 # 个数可以多个,但是需首位个数一致。
在字面量里 放置 扩展分隔符, 可以让其包含的特殊字符不生效。
let str = #"Line1 \nLine2"#
print(str) // Line1 \nLine2, \n不生效
如果需要让特殊字符生效, 可以在特殊字符之前加上 与 首尾相同个数的 # 来实现
let str = #"Line1 \#nLine2"#
print(str)
// Line1
Line2
let str = ###"Line1 \###nLine2"###
print(str)
// Line1
Line2
字符串的常见操作
字符串的可变性表示
不同于OC的 不可变用NSString
表示, 可变用NSMutableString
表示。
Swift中,是否可变 还是通过 let
和 var
表示, let
表示不可变, var
表示可变, Swift的方式更加统一。
let str = "abc"
str += "def" // error
var str = "abc"
str += "def" // abcdef
字符串是值类型
不同于OC的字符串是对象类型,Swift中的字符串是值类型。
所以 String值,在传递给函数的时候会被复制过去的,是两份不同的副本。
值得注意的是, Swift编译器优化了字符串使用的资源, 只有在
确实需要
的时候才会进行实际上的拷贝。
var str = "abc" // abc
var str1 = str // abc
print(str == str1) // true
str += "def" // abcdef
print(str == str1) //false
print(str) // abcdef
print(str1) // abc
操作字符
String中的每一个字符都是 Character 类型,可以使用如下方式操作字符。
- for-in循环遍历String中的每一个独立的 Character。
let str = "hello"
for c in str {
print(c) // "h" "e" "l" "l" "o"
- 使用索引操作字符
每一个String值都有相关的索引类型 : String.index, 它相当于每个Character在字符串中的位置。
startIndex
属性用来访问 String 中的第一个字符的位置,endIndex
用来访问String中的最后一个字符位置,endIndex
并不是字符串下标脚本的合法实际参数, 如果String为空, 则startIndex
和endIndex
相等.
let str = "hello"
str[tr.startIndex] // "h"
str[1] //error!!! index 实际类型是struct 而不是int
使用index(before:)
和 index(after:)
方法来访问给定索引的前后。
使用index(_:offsetBy:)
方法来访问给定索引 的指定偏移索引
使用indices
属性来访问字符串中每个字符的索引
let str = "hello"
str[str.index(before:str.endIndex)] // "o"
str[str.index(after:str.startIndex)] // "e"
let index = str.index(str.startIndex, offsetBy:3)
str[index] // "l"
字符串拼接
- 使用加运算符 + ,创建新字符串。
- 使用 +=, 在原字符串后面拼接新串。
- 使用String类型的 append() 方法来给原字符串末尾追加 Character 值。
var str = "hello,"
var str1 = "world"
var newStr = str + str1
print(str) // "hello,"
print(newStr) // "hello,world"
var str += str1
print(str) // "hello,world"
字符串插值
字符串插值是一种从混合常量,变量,字面量和表达式的字符串字面量构造新String值的方法。
它类似于OC中 NSString
的 stringWithFormat
方法
每一个插入到字符串字面量的元素都要被一对小括号包裹,并使用反斜杠前缀: \()
let num = 3
let str = "times"
let message = "\(num) \(str) 2.5 is \(Double(num) * 2.5)" // 3 times 2.5 is 7.5
可以在 Raw String 中创建一个包含在其他情况下会被当作字符串插值的字符。
要在使用 Raw String 的字符串中使用 字符串插值, 仍然需要在反斜杠 \ 后 ,使用 匹配首尾 # 数量的 #。
print(#"\(3) \("times") 2.5 is \(Double(3) * 2.5"#)
// \\(3) \\("times") 2.5 is \\(3 * 2.5)\n
print(#"\#(3) \#("times") 2.5 is \#(Double(3) * 2.5"#)
// 3 times 2.5 is 7.5
插入
- 插入字符:使用
insert(:_at:)
方法 - 插入另一个字符串的内容到指定的索引, 使用
insert(contentsOf:at:)
方法
var str = "hello"
str.insert("!" at: str.endIndex) // "hello!\n"
str.insert(contentsOf:" world", at: str.index(befor:str.endIndex)) // "hello world!\n"
删除
- 移除字符: 使用
remove(at:)
方法 - 移除特定范围内的字符串, 使用
removeSubrange(_:)
方法
var str = "hello world!"
str.remove(at: str.index(before:str.endIndex)) // "hello world\n"
let range = str.index(str.endIndex, offsetBy: -6..<str.endIndex)
str.removeSubrange:(range) // "hello\n"
子字符串
在Swift中, 使用下标或者类似 prefix(_:)
方法得到的子字符串 是Substring类型
Substring 拥有 String 的大部分方法, 也可以转成 String
let str = "hello, world!"
let index = str.index(of: ",") ?? str.endIndex
let begin = str[..<index]
let newStr = String(begin)
为什么Swift用Substring表示子字符串:
主要为性能考虑:
- 子字符串可以重用原字符串的一部分内存
- 修改字符串或者子字符串之前都不需要花费拷贝内存的代价
- String和Substring都遵循 StringProtocol 协议, 也就是说它基本上能很方便地兼容所有接受 StringProtocol 值的字符串操作函数。
字符串比较
- 使用 == 或 != 来比较字符串和字符的相等性
- 使用
hasPrefix(_:)
方法 判断前缀相等性 - 使用
hasSuffix(_:)
方法 判断后缀相等性
let str = "hello"
let str1 = "hello, world!"
print(str == str1) //false
print(str.hasPrefix("hello")) //true
print(str1.hasSuffix("world!")) //true