Swift4.0 新特性----字符串改进
程序员文章站
2022-03-11 16:39:55
...
注:文章转自这里
1.Unicode 字符串在计算 count 时的正确性改善
在 Unicode 中,有些字符是由几个其它字符组成的,比如 é 这个字符,它可以用 \u{E9} 来表示,也可以用 e 字符和上面一撇字符组合在一起表示 \u{65}\u{301}。
看以下代码:
var family = "x"
family += "\u{200D}x"
family += "\u{200D}x"
family += "\u{200D}x"
print(family)
print(family.characters.count)
这个 family 是一个由多个字符组合成的字符,打印出来的结果是一个特殊的emoji表情。上面的代码在 Swift 3 中打印的 count 数是 4,在 Swift 4 中打印出的 count 是 1。
2.更快的字符处理速度
Swift 4 的字符串优化了底层实现,对于英语、法语、德语、西班牙语的处理速度提高了 3.5 倍。
对于简体中文、日语的处理速度提高了 2.5 倍。(数据来源于官方PPT)
Swift 3 中的 String 需要通过 characters 去调用的属性方法,在 Swift 4 中可以通过 String 对象本身直接调用,例如:
Swift 4 可以把上面代码中的所有的 characters 都去掉,修改如下:
Swift 4:
Swift 4 中 String 可以当做 Collection 来用,并不是因为 String 实现了 Collection 协议,而是 String 本身增加了很多 Collection 协议中的方法,使得 String 在使用时看上去就是个 Collection。例如:
翻转字符串:
遍历字符:
Map、Filter、Reduce:
在 Swift 中,String 的背后有个 Owner Object 来跟踪和管理这个 String,String 对象在内存中的存储由内存起始地址、字符数、指向 Owner Object 指针组成。Owner Object 指针指向 Owner Object 对象,Owner Object 对象持有 String Buffer。当对 String 做取子字符串操作时,子字符串的 Owner Object 指针会和原字符串指向同一个对象,因此子字符串的
Owner Object 会持有原 String 的 Buffer。当原字符串销毁时,由于原字符串的 Buffer 被子字符串的 Owner Object 持有了,原字符串 Buffer 并不会释放,造成极大的内存浪费。
在 Swift 4 中,做取子串操作的结果是一个 Substring 类型,它无法直接赋值给需要 String 类型的地方。必须用 String() 包一层,系统会通过复制创建出一个新的字符串对象,这样原字符串在销毁时,原字符串的 Buffer 就可以完全释放了。
3.去掉 characters
let values = "one,two,three..."
var i = values.characters.startIndex
while let comma = values.characters[i...<values.characters.endIndex].index(of: ",") {
if values.characters[i..<comma] == "two" {
print("found it!")
}
i = values.characters.index(after: comma)
}
Swift 4 可以把上面代码中的所有的 characters 都去掉,修改如下:
let values = "one,two,three..."
var i = values.startIndex
while let comma = values[i...<values.endIndex].index(of: ",") {
if values[i..<comma] == "two" {
print("found it!")
}
i = values.index(after: comma)
}
4.One-sided Slicing
Swift 4 新增了一个语法糖 ... 可以对字符串进行单侧边界取子串。
Swift 3:let values = "abcdefg"
let startSlicingIndex = values.index(values.startIndex, offsetBy: 3)
let subvalues = values[startSlicingIndex..<values.endIndex]
Swift 4:
let values = "abcdefg"
let startSlicingIndex = values.index(values.startIndex, offsetBy: 3)
let subvalues = values[startSlicingIndex...] // One-sided Slicing
5.String 当做 Collection 来用
翻转字符串:
let abc: String = "abc"
print(String(abc.reversed()))
// cba
遍历字符:
let abc: String = "abc"
for c in abc {
print(c)
}
/*
a
b
c
*/
Map、Filter、Reduce:
// map
let abc: String = "abc"
_ = abc.map {
print($0.description)
}
// filter
let filtered = abc.filter { $0 == "b" }
// reduce
let result = abc.reduce("1") { (result, c) -> String in
print(result)
print(c)
return result + String(c)
}
print(result)
6.Substring
在 Swift 4 中,做取子串操作的结果是一个 Substring 类型,它无法直接赋值给需要 String 类型的地方。必须用 String() 包一层,系统会通过复制创建出一个新的字符串对象,这样原字符串在销毁时,原字符串的 Buffer 就可以完全释放了。
let big = downloadHugeString()
let small = extractTinyString(from: big)
mainView.titleLabel.text = small // Swift 4 编译报错
mainView.titleLabel.text = String(small) // 编译通过
7.多行字符串字面量
func tellJoke(name: String, character: Character) {
let punchline = name.filter { $0 != character }
let n = name.count - punchline.count
let joke = "Q: Why does \(name) have \(n) \(character)'s in their name?\nA: I don't know, why does \(name) have \(n) \(character)'s in their name?\nQ: Because otherwise they'd be called \(punchline)."
print(joke)
}
tellJoke(name: "Edward Woodward", character: "d")
字符串中间有换行只能通过添加 \n 字符来代表换行。
Swift 4 可以把字符串写在一对 """ 中,这样字符串就可以写成多行。
func tellJoke(name: String, character: Character) {
let punchline = name.filter { $0 != character }
let n = name.count - punchline.count
let joke = """
Q: Why does \(name) have \(n) \(character)'s in their name?
A: I don't know, why does \(name) have \(n) \(character)'s in their name?
Q: Because otherwise they'd be called \(punchline).
"""
print(joke)
}
tellJoke(name: "Edward Woodward", character: "d")