原文:Exploring the new String API in Swift 4 — Swift by Sundelljavascript
WWDC 已经结束了(我以为是自 2014 年来最好的一场 WWDC),同时 Xcode 9 beta 版也发布了,不少开发者已经开始把玩 Swift 4 ,今年的新版本真心不错,这是一个改进版本而不是重构版本(像 Swift 2 和 3),所以大多数代码升级起来会更容易。java
其中一个改进是 String 的 API,在 Swift 4 中更易用,也更强大。在过去的 Swift 版本中,String API 常常被提出为一个例子用来讲明正确性,以繁琐的方式处理字符和子串。git
本周,咱们来看看在 Swift 4 中如何使用 String,以及如何在各类状况下利用新的改进的 API。程序员
有时咱们的应用或脚本中有很长的静态字符串会跨越多行。在 Swift 4以前,咱们只能在字符串之间插入 \n
来换行,appendOnNewLine()
经过给 String 添加一个 extension
方法,屡次 print()
来添加换行符用来大段文本输出。github
译者注:这里的脚本指的是命令行程序swift
好比,下面是 TestDrive
的 printHelp()
方法(用于打印脚本的使用说明)在 Swift 3 看起来以下:api
func printHelp() {
print("🚘 Test Drive")
print("--------------")
print("Quickly try out any Swift pod or framework in a playground.")
print("\nUsage:")
print("- Simply pass a list of pod names or URLs that you want to test drive.")
print("- You can also specify a platform (iOS, macOS or tvOS) using the '-p' option")
print("- To use a specific version or branch, use the '-v' argument (or '-m' for master)")
print("\nExamples:")
print("- testdrive Unbox Wrap Files")
print("- testdrive https://github.com/johnsundell/unbox.git Wrap Files")
print("- testdrive Unbox -p tvOS")
print("- testdrive Unbox -v 2.3.0")
print("- testdrive Unbox -v swift3")
}复制代码
Swift 4 中处理多行文本字符串:app
func printHelp() {
print(
"""
🚘 Test Drive
--------------
Quickly try out any Swift pod or framework in a playground.
Usage:
- Simply pass a list of pod names or URLs that you want to test drive.
- You can also specify a platform (iOS, macOS or tvOS) using the '-p' option
- To use a specific version or branch, use the '-v' argument (or '-m' for master)
Examples:
- testdrive Unbox Wrap Files
- testdrive https://github.com/johnsundell/unbox.git Wrap Files
- testdrive Unbox -p tvOS
- testdrive Unbox -v 2.3.0
- testdrive Unbox -v swift3
"""
)
}复制代码
如上所示,当使用多行文本字符串时,代码会表示得更加清楚和整洁,咱们不须要再添加不少 \n
换行符,而是简单地在字符串中添加真正的换行符,使得在运行脚本以前,能够很容易地看到输出后的样子。框架
在缩进方面,多行文本字符串使用底部的 """
来肯定字符串的基础缩进,因此跟这些引号对齐的全部内容都不会在字符串中进行额外的真实缩进。工具
在 Swift 1 中,String 遵循了 CollectionType
(Swift 3+ 中的 Collection
)协议,这意味着您能够对它们执行各类收集操做(好比 forEach()
,filter()
等)。 您仍然能够在 Swift 2 & 3 中进行此操做,经过访问 characters
属性,但这很快会致使阅读代码更难。
Swift 4 中字符串再次成为了集合对象,这意味着你能够简单地将它们视为“字符集合”。这可能会颇有用,好比从字符串中过滤出某些字符(让咱们以叹号为例):
let filtered = string.filter { $0 != "!" }复制代码
Swift 4 引入了一种处理子字符串的新方法,使用了一个彻底不一样的类型 Substring 。如今大多数方法都会返回 Substring(如 split()
),而且还引入了一个新的 subscripting API,让你能够快速访问一个子字符串:
// 从一个置顶的
let substring = string[index...]复制代码
咱们来看一个例子,咱们截断用户输入的文本返回一个子字符串,将其限制在必定长度。在 Swift 3 中,你会写成这样:
extension String {
func truncated() -> String {
return String(characters.prefix(truncationLimit))
}
}复制代码
(编辑注释:我以前用的是一个更复杂的例子,感谢 Ole Begemann 指出这个更好的解决方案)
好消息是,因为 Swift 4 代码大多数兼容 Swift 3,因此上述代码一样能够在 Swift 4 下运行。但更好的消息是,因为 String 在 Swift 4 中是集合类型,咱们能够直接简化上述代码为:
extension String {
func truncated() -> Substring {
return prefix(truncationLimit)
}
}复制代码
上面用 prefix()
方法返回最多为 n 个元素的子序列,同时包括边界检查(若是咱们的集合(这里是字符串)包含少于 n 个元素的时候,以防咱们不会遇到错误)。
你能够看到上面的 truncated()
方法的返回类型如今是新的 Substring 类型。虽然起初看起来很累赘由于字符串现是一个不一样的类型,但它在内存可预测性方面给了咱们很大的优点。
为了不建立许多冗余拷贝,Swift 字符串使用 “copy on write” 方式只须要在须要时进行拷贝。这意味着子字符串一般与内存中的父字符串共享相同的底层缓冲区。可是在 truncated()
这个例子中,咱们不想在内存中保留整个未截断的字符串,只是为了可以使用截断的子字符串。
经过给咱们一个 Substring 类型,而不是一个完整的 String,Swift 如今 “强制” 咱们在须要时显式拷贝副本,让父字符串的内存能够被释放。咱们能够简单地从截取的子字符串建立一个新的 String ,以下所示:
label.text = String(userInput.truncated())复制代码
因为几乎全部的 Swift 应用和脚本都会处理字符串,因此很高兴能看到这些 API 的改进。我认为新的 API 是在正确性和易用性之间的一个很好的权衡,同时也要求程序员在 copy 时慎重选择,像 Substring 同样。
我没有在这篇文章中介绍的字符串 API 也有更多的进步,好比 Unicode 9 支持更简单的字符管理,而且可以轻松访问构成字符的底层 Unicode 代码。
咱们将在即将发布的后续文章包括 WWDC 中发布的其余新的 Swift 4 API 、框架、工具中深刻研究字符串处理和编码。敬请关注!😉
如何在 Swift 4 中找到新的 String API?String 如今是集合类型真的会让你的字符串处理更简单吗?若是你有相似问题或其余问题请让我知道,意见或反馈能够在这里评论或 Twitter @johnsundell。
感谢阅读!🚀