内容简介:作者:Olivier Halligon,译者:
作者:Olivier Halligon, 原文链接 ,原文日期:2018-12-15
译者: Nemocdz ;校对: numbbbbb , Yousanflics ;定稿: Forelax
StringInterpolation
协议最初的设计效率低下又不易扩展,为了在后续的版本中能够将其彻底重构,Swift 4 中将该协议标记为废弃。即将在 Swift 5 中亮相的 SE-0228
提案介绍了一种新的 StringInterpolation
设计,使得 String 有了更大的潜能。
在 Swift 的 master
分支里实现之后,就可以下载一个 快照
来安装最新的 Swift 5 工具 链到 Xcode 中,来尝试全新的 StringInterpolation
。让我们来把玩一下。
全新的 StringInterpolation 设计
我强烈建议本篇文章的读者阅读一下 SE-0228 提案,感受一下新 API 的背后的设计思路和动机。
要让一个类型遵循 ExpressibleByStringInterpolation
,最基本的你需要:
-
让这个类型拥有一个类型为
StringInterpolation的子类型,这个子类型遵循StringInterpolationProtocol并将负责解释插值 -
这个子类型仅需要实现
appendLiteral(_ literal: String)方法,再选择一个或多个你自己想要支持的appendInterpolation(...)签名的方法 -
这个
StringInterpolation子类型会作为“构造器”服务于你的主类型,然后编译器会调用那些append…方法一步一步地构造对象 -
然后你的主类型需要实现
init(stringInterpolation: StringInterpolation),它会用上一步的结果来实例化它自己。
你可以实现任何你喜欢的 appenInterpolation(...)
方法,这意味着你可以任意选择支持什么插值。这是一个带来巨大的可能性的超强功能。
举个例子,如果你实现了 func appendInterpolation(_ string: String, pad: Int)
,那么意味着你将可以用类似这样的插值: "Hello \(name, pad: 10), how are you?"
来构造你的类型。插值只需要匹配你的 StringInterpolation
子类型其中一个支持的 appendInterpolation
方法签名。
一个简单的例子
让我用一个简单的例子来演示一下插值是如何运作的。一起来构造一个允许引用 issue 编号和用户的 GitHubComment
类型吧。
这个例子的目标是做到类似下面的写法:
let comment: GitHubComment = """ See \(issue: 123) where \(user: "alisoftware") explains the steps to reproduce. """
所以我们该怎么实现它呢?
首先,让我们声明基本的结构体 struct GitHubComment
并让它遵循 ExpressibleByStringLiteral
(因为 ExpressibleByStringInterpolation
继承自这个协议所以我们将它的实现抽离)和 CustomStringConvertible
(为了 debug 时友好地在控制台中打印)。
struct GitHubComment {
let markdown: String
}
extension GitHubComment: ExpressibleByStringLiteral {
init(stringLiteral value: String) {
self.markdown = value
}
}
extension GitHubComment: CustomStringConvertible {
var description: String {
return self.markdown
}
}
然后,我们让 GitHubComment
遵循 ExpressibleByStringInterpolation
。这意味着在剩下需要实现的功能,将由一个 StringInterpolation
子类型来完成:
-
首先初始化它自己:
init(literalCapacity: Int, interpolationCount: Int)提供给你保留一部分数据到缓冲区的能力,在一步步构造类型时就会用到这个能力。在这个例子中,我们可以在构造实例的时候,简单用一个String并往它上面追加片段,不过这里我采用一个parts: [String]来代替,之后再将它组合起来 -
实现
appendLiteral(_ string: String)逐个追加文本到parts里 -
实现
appendInterpolation(user: String)在遇到\(user: xxx)时逐个追加 markdown 表示的用户配置链接 -
实现
appendInterpolation(issue: Int)逐个追加用 markdown 表示的 issue 链接 -
然后在
GitHubComment上实现init(stringInterpolation: StringInterpolation)将parts构造成一个评论
extension GitHubComment: ExpressibleByStringInterpolation {
struct StringInterpolation: StringInterpolationProtocol {
var parts: [String]
init(literalCapacity: Int, interpolationCount: Int) {
self.parts = []
// - literalCapacity 文本片段的字符数 (L)
// - interpolationCount 插值片段数 (I)
// 我们预计通常结构会是像 "LILILIL"
// — e.g. "Hello \(world, .color(.blue))!" — 因此是 2n+1
self.parts.reserveCapacity(2*interpolationCount+1)
}
mutating func appendLiteral(_ literal: String) {
self.parts.append(literal)
}
mutating func appendInterpolation(user name: String) {
self.parts.append("[\(name)](https://github.com/\(name))")
}
mutating func appendInterpolation(issue number: Int) {
self.parts.append("[#\(number)](issues/\(number))")
}
}
init(stringInterpolation: StringInterpolation) {
self.markdown = stringInterpolation.parts.joined()
}
}
这就完事了!我们成功了!
注意,因为那些我们实现了的 appendInterpolation
方法签名,我们允许使用 Hello \(user: "alisoftware")
但不能使用 Hello \(user: 123)
,因为 appendInterpolation(user:)
期望一个 String
作为形参。类似的是,在你的字符串中 \(issue: 123)
只能允许一个 Int
因为 appendInterpolation(issue:)
采用一个 Int
作为形参。
实际上,如果你尝试在你的 StringInterpolation
子类中用不支持的插值,编译器会给你提示报错:
let comment: GitHubComment = """ See \(issue: "bob") where \(username: "alisoftware") explains the steps to reproduce. """ // ^~~~~ ^~~~~~~~~ // 错误: 无法转换 ‘String’ 类型的值到期望的形参类型 ‘Int’ // 错误: 调用 (have 'username:', expected 'user:')实参标签不正确
这仅仅只是个开始
这个新的设计打开了一大串脑洞让你去实现自己的 ExpressibleByStringInterpolation
类型。这些想法包括:
-
创建一个
HTML类型并遵循,你就可以用插值写 HTML -
创建一个
SQLStatement类型并遵循,你就可以写更简单的 SQL 语句 -
用字符串插值支持更多自定义格式,比如在你的插值字符串中用格式化
Double或者Date值 -
创建一个
RegEX类型并遵循,你就可以用花里胡哨的语法写正则表达式 -
创建一个
AttributedString类型并遵循,就可以用字符串插值构建NSAttributedString
带来新的字符串插值设计的 Brent Royal-Gordon 和 Michael Ilseman ,提供了更多例子在这个 要点列表 中。
我个人尝试了一下支持 NSAttributedString
的实现,并想 在专门的一篇文章里分享它的初步实现
,因为我发现它非常优雅。我们下一篇文章再见!
本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问http://swift.gg。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Swift 5 字符串插值之美
- 木兰重生:与 Python 生态的兼容问题;字符串插值
- 查找--插值查找(Java)
- R_空间插值_必知必会(二)
- 实现opencv中常用的三种插值算法
- 另一种(Yet Another)三角形线性插值方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
断点:互联网进化启示录
[美]杰夫·斯蒂贝尔 / 师蓉 / 中国人民大学出版社有限公司 / 2014-11-1 / CNY 49.00
一部神经学、生物学与互联网技术大融合的互联网进化史诗巨著。 我们正置身网络革命中。互联网的每一丝变化都与你我息息相关。当科技变得无处不在时,它就会改变你我。在《断点》一书中,大脑科学家和企业家杰夫·斯蒂贝尔将带领读者来到大脑、生物与技术的交汇处,向读者展示生物学和神经学是如何与互联网技术发生联系的;我们是如何通过生物学上的前车之鉴,来预测互联网的发展的;互联网在经历增长、断点和平衡后又会发生......一起来看看 《断点:互联网进化启示录》 这本书的介绍吧!