当前位置: 首页 > news >正文

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

本文讲的是[译] 探索 Swift 4 中新的 String API,

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() 来添加换行符用来大段文本输出。

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

比如,下面是 TestDrive 的 printHelp() 方法(用于打印脚本的使用说明)在 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 、框架、工具中深入研究字符串处理和编码。敬请关注!






原文发布时间为:2017年6月12日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。

相关文章:

  • 右键添加复制路径选项
  • cocos2d-x支持c++、js、lua开发
  • 旋转数组中查找最小值-剑指Offer11
  • RIP路由信息协议
  • 服务器连接工具 secureCRT
  • SeaweedFS---01
  • Spring Boot 最佳实践(五)Spring Data JPA 操作 MySQL 8
  • 周六相约橘子洲头,共话AWS上的AI和大数据技术
  • 【转】20-TCP 协议(滑动窗口——基础)
  • httpd之apache服务器配置
  • 如何重置migration
  • LVS 之 管理工具ipvsadm介绍
  • JDBC 结构
  • 【以太坊】雷电网络的101网络原理概述
  • @property @synthesize @dynamic 及相关属性作用探究
  • es6要点
  • Fastjson的基本使用方法大全
  • Golang-长连接-状态推送
  • JAVA_NIO系列——Channel和Buffer详解
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • node 版本过低
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • Rancher-k8s加速安装文档
  • Webpack 4x 之路 ( 四 )
  • windows下使用nginx调试简介
  • 半理解系列--Promise的进化史
  • 好的网址,关于.net 4.0 ,vs 2010
  • 爬虫模拟登陆 SegmentFault
  • 判断客户端类型,Android,iOS,PC
  • 前端设计模式
  • 我有几个粽子,和一个故事
  • 硬币翻转问题,区间操作
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • Prometheus VS InfluxDB
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​卜东波研究员:高观点下的少儿计算思维
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #FPGA(基础知识)
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #pragma 指令
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • %@ page import=%的用法
  • (层次遍历)104. 二叉树的最大深度
  • (九)c52学习之旅-定时器
  • (四) Graphivz 颜色选择
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .“空心村”成因分析及解决对策122344
  • .Net Memory Profiler的使用举例
  • /etc/sudoer文件配置简析