特性:
1. Unicode 编码规范: 可以使用任何字符,表情
2. 与本地语言无关:无需去考虑汉子及其他字体乱码以及转码问题
3. 高效
4. 值类型:无论作为参数传递还是复制给别的常量或变量都会copy一份(是否真正copy一份在内存中取决于编译器的优化决定)
5. 与 NSString 兼容
String 的初始化方式
使用字符串常量值初始化
var str = ""
var str1 = "Hello, playground"
使用 init 方法初始化
1. 字符串常量值初始化
// str3, str4 效果与str, str1 效果相同,
let str3 = String()
let str4 = String("Hello, playground")
2. charater及数组初始化
let ch:Character = "A"
let str5 = String(ch)let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
3. CharacterView 作为参数初始化
String 的 CharacterView 属性是一个扩张字符簇的集合,它近似于人的可读字符。一些独立的字符, 如é”, “김”, and “🇮🇳 是由多个unicode 代码点组成,é(e\u{301}), 这些代码点通过Unicode的边界算法组 合成扩张字符簇中的字符,这个字符就是swift 中的Charater类型,CharacterView 中的每一个元素就 是一个Charater, 我们可以把CharacterView 看做是Charater的一个集合
let poem = "'Twas brillig, and the slithy toves / " + "Did gyre and gimbal in the wabe: / " + "All mimsy were the borogoves / " + "And the mome raths outgrabe."
let result = poem.characters
print(result)
输出结果 :CharacterView(_core: Swift._StringCore(_baseAddress: Optional(0x0000600000177de0), _countAndFlags: 132, _owner: Optional(Swift._HeapBufferStorage)))
我们可以把这个结果转成数组 print(Array (result))
let excerpt = String(poem.characters.prefix(22)) + "..." // charaterView 初始化
print(excerpt)
CharacterView 只是swift中的一种编码形式,还有其他三种
Unicode Scalar View
String 的 unicodeScalars 属性是unicode 标量的集合,基本的unicode占21个比特位。每一个unicodeScalar表示的标量等同于UTF-32。
UTF-16 View:
String 的 utf16 属性是一个utf-16的编码集,每一个编码单元都是一个utf-16实例,占据16bit。在OC中,NSString的编码方式就是utf16
UTF-8 View
String 的 utf8 属性是一个utf-8的编码集,每一个编码单元都是一个utf-8实例 占据8bit。当把String实例传给c APIs时使用的就是这种编码形式。
不同的字符编码形式所占的空间不同所以每一个编码单元所能表示的范围也不同,同一个字符串在不同的编码形式下会有不同的存储形式,会有不同的长度。
let cafe = "Cafe\u{301} du 🌍"
print(Array(cafe.characters))
print(cafe.unicodeScalars.map { $0.value })
print(Array(cafe.utf16))
print(Array(cafe.utf8))
结果:`
["C", "a", "f", "é", " ", "d", "u", " ", "🌍"]
[67, 97, 102, 101, 769, 32, 100, 117, 32, 127757]
[67, 97, 102, 101, 769, 32, 100, 117, 32, 55356, 57101]
[67, 97, 102, 101, 204, 129, 32, 100, 117, 32, 240, 159, 140, 141]
从文件中初始化
do {
let abc = try String(contentsOfFile:"123", encoding:String.Encoding.utf8)
print(abc)
} catch {
}
长度计算
通过 character.count 计算字符串的长度,由于字符串采用的是扩张的字符集, 所以在一些情况下即使发生了修改其长度也可能不会这化
var word = "cafe"
print("the number of characters in \(word) is \(word.characters.count)")
// Prints "the number of characters in cafe is 4"
word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
print("the number of characters in \(word) is \(word.characters.count)")
// Prints "the number of characters in café is 4”
访问和修改字符串
就像我们上面提到的,String在不同的编码下所占的内存空间是完全不同的,所以我们无法通过一个整型的下标值来定位一个字符的位置,如果想要通过下标来访问这样的方式来访问,我们就要用到String.Index。
startIndex: 第一个字符所在的位置
endIndex: 最后一个字符的下一位所在的位置
var str = "Cafe\u{301} du 🌍"
print(str.characters.count)
print(str[str.startIndex])
print(str[str.index(after: str.startIndex)])
let index = str.index(before: str.endIndex)
print(str[index])
如果想改变原字符串使用append
var a = "Hello"
a.append("abc")
print(a) // Helloabc
a 必须是变量
通过after 和before可以找到当前Index的上个位置或下一个位置.
let index = str.index(str.startIndex, offsetBy: 5)
print(str[index])
如果采用上面的方法,当结果超出endIndex 时就会报错,我们可以采用下面的方法来防止这样的错误发生,如果超出时就返回nil
let indexN = str.index(str.startIndex, offsetBy: 20, limitedBy: str.endIndex)
查找字符串的位置:
let index = str.characters.index(of: "a");
//查找第一个大写字母
let greeting = "hello, friEnd!"
if let i = greeting.characters.index(where: { $0 >= "A" && $0 <= "a" }) {
print("First capital letter: \(greeting[i])")
}
连接,格式化
连接两个字符串,并生成一个新的字符串
let a = "Hello"
let b = "World"
let c = a + b
print(a) // Hello
print(b) // World
print(c) // HelloWorld
let count = 10;
let result = "The result is \(count)"
print(result)