Swift -- 字符和字符串
字符和字符串
字符串是例如"hello, world","albatross"这样的有序的Character(字符)类型的值的集合。通过String类型来表示。 一个String的内容可以用许多方式读取,包括作为一个Character值的集合。
Swift 的String和Character类型提供了快速和兼容 Unicode 的方式供你的代码使用。创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。 字符串连接操作只需要简单地通过+符号将两个字符串相连即可。与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。你也可以在字符串内插过程中使用字符串插入常量、变量、字面量表达成更长的字符串,这样可以很容易的创建自定义的字符串值,进行展示、存储以及打印。
尽管语法简易,但String类型是一种快速、现代化的字符串实现。 每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式(representations)。
注意:
Swift 的String类型与 Foundation NSString类进行了无缝桥接。Foundation 也可以对String进行扩展,暴露在NSString中定义的方法。 这意味着,如果你在String中调用这些NSString的方法,将不用进行转换。
字符串的字面量
你可以在您的代码中包含一段预定义的字符串值作为字符串字面量。字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集。 字符串字面量可以用于为常量和变量提供初始值:
let str = "hello world"
let someString = "Some string literal value"
初始化空字符串
要创建一个空字符串作为初始值,可以将空的字符串字面量赋值给变量.
以初始化一个 string 为例:
var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化方法
// 两个字符串均为空并等价。
可以通过检查其Bool类型的isEmpty属性来判断该字符串是否为空
if emptyString.isEmpty {
print("Nothing to see here")
}
// 打印输出:"Nothing to see here"
字符串可变性
- 可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改
var variableString = "Horse"
variableString += " and carriage"
// variableString 现在为 "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// 这会报告一个编译错误 (compile-time error) - 常量字符串不可以被修改。
注意:
在 Objective-C 和 Cocoa 中,您需要通过选择两个不同的类(NSString和NSMutableString)来指定字符串是否可以被修改。
- 字符串是值类型
Swift 的String类型是值类型。 如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。 任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作。
实际上,在 Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且在底层都是以结构体的形式所实现。
在 Swift 中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制。
- Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值。 很明显无论该值来自于哪里,都是你独自拥有的。 你可以确信传递的字符串不会被修改,除非你自己去修改它。
- 在实际编译时,Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着您你字符串作为值类型的同时可以获得极高的性能。
遍历字符串
可通过for-in循环来遍历字符串中的characters属性来获取每一个字符的值
let name = "chinese😆"
for str in name.characters {
print(str)
}
依次打印出来的是:
c
h
i
n
e
s
e
😆
for character in "Dog!🐶".characters {
print(character)
}
// D
// o
// g
// !
// 🐶
注: 关于 for- in 语句 后面会详细讲
character 和 String 的关系
Swift 中 character 类型 表示单子字符. String 类型表示一个字符串,类似于 C 语言中的字符集合.
通过标明一个Character类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量
let exclamationMark: Character = "!"
let temp: Character = "123" // 会报错 cannot convert value of type 'String' to specified type 'Character'
字符串可以通过传递一个值类型为Character的数组作为自变量来初始化:
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// 打印输出:"Cat!🐱"
连接字符串和字符
字符串可以通过加法运算符(+)相加在一起(或称“连接”)创建一个新的字符串
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome 现在等于 "hello there"
也可以通过加法赋值运算符 (+=) 将一个字符串添加到一个已经存在字符串变量上
var instruction = "look over"
instruction += string2
// instruction 现在等于 "look over there"
可以用append()方法将一个字符附加到一个字符串变量的尾部
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome 现在等于 "hello there!"
注意:
不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
字符串插值
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。 您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5"
在上面的例子中,multiplier作为(multiplier)被插入到一个字符串常量量中。 当创建字符串执行插值计算时此占位符会被替换为multiplier实际的值。
multiplier的值也作为字符串中后面表达式的一部分。 该表达式计算Double(multiplier) * 2.5的值并将结果 (7.5) 插入到字符串中。 在这个例子中,表达式写为(Double(multiplier) * 2.5)并包含在字符串字面量中。
注意:
插值字符串中写在括号中的表达式不能包含非转义反斜杠 (\),并且不能包含回车或换行符。不过,插值字符串可以包含其他字面量。
访问和修改字符串
你可以通过字符串的属性和方法来访问和修改它,当然也可以用下标语法完成。
字符串索引
每一个String
值都有一个关联的索引(index)类型,String.Index
,它对应着字符串中的每一个Character
的位置。
前面提到,不同的字符可能会占用不同数量的内存空间,所以要知道Character
的确定位置,就必须从String
开头遍历每一个 Unicode 标量直到结尾。因此,Swift 的字符串不能用整数(integer)做索引。
使用startIndex
属性可以获取一个String
的第一个Character
的索引。使用endIndex
属性可以获取最后一个Character
的后一个位置的索引。因此,endIndex
属性不能作为一个字符串的有效下标。如果String
是空串,startIndex
和endIndex
是相等的。
通过调用String
的index(before:)
或index(after:)
方法,可以立即得到前面或后面的一个索引。还可通过调用index(_:offsetBy:)
方法来获取对应偏移量的索引,这种方式可以避免多次调用index(before:)
或index(after:)
方法。
可以使用下标语法来访问String
特定索引的Character
。