[译] 探索 Swift 4 中新的 String API

原文:[Exploring the new String API in Swift 4](Exploring the new String API in Swift 4 — Swift by Sundell)

WWDC 已经结束了(我觉得是自 2014 年来最好的一场 WWDC),同时 Xcode 9 beta 版也发布了,很多开发者已经开始把玩 Swift 4 ,今年的新版本真心不错,这是一个改进版本而不是重构版本(像 Swift 2 和 3),因此大多数代码升级起来会更容易。

其中一个改进是 String 的 API,在 Swift 4 中更易用,也更强大。在过去的 Swift 版本中,String API 经常被提出为一个例子用来说明正确性,以繁琐的方式处理字符和子串。

本周,我们来看看在 Swift 4 中如何使用 String,以及如何在各种情况下利用新的改进的 API。

多行字符串

有时我们的应用或脚本中有很长的静态字符串会跨越多行。在 Swift 4之前,我们只能在字符串之间插入 \n 来换行,appendOnNewLine() 通过给 String 添加一个 extension 方法,多次 print() 来添加换行符用来大段文本输出。

译者注:这里的脚本指的是命令行程序

比如,下面是 TestDriveprintHelp() 方法(用于打印脚本的使用说明)在 Swift 3 看起来如下:

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 中处理多行文本字符串:

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 != "!" }

新的 Substring 类型

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

感谢阅读!🚀

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容