Swift 3 字符串的进化

原文: Updating Strings for Swfit 3
作者: kharrison
译者: kemchenj

我去年写了一篇 Swift String Cheat Sheet 来帮助我记忆如何使用 Swift 标准库里的那些难用的 API, 在痛苦的版本迁移之后, Swift 3有了明显的改善, 这一部分得归功于新的 API 命名规范, 还有 Collections 集合, indicates 索引和 ranges 范围的一种新的运作方式.

这里有我关于 Swift 3的迁移工作的总结 Swift playground.

更好的 API 命名

标准库采用了新的 API 命名规范 API guidelines 之后, String 的属性和方法都有了很多改变. 因为大部分 API 命名的变化 Xcode 都会自动帮你修正, 所以我不会在这里把全都都列出来. 这里列出一些典型的改变让你能更好的了解这次变化:

初始化一个 String

标准库把 String 的初始化方法 init(count: repeatedValue:) 改成了 init(repeating: count:), repeatedValue 的类型也从 Character 字符换成了 String 字符串去获得更多灵活性:

// Swift 2
let h = String(count:3, repeatedValue:"0") // "000"

// Swift 3
let h = String(repeating:"01", count:3)    // 010101

大小写转换

uppercaseStringlowercaseString 两个属性现在变成了函数, 重新命名为 uppercased()lowercased():

let mixedCase = "AbcDef"

// Swift 2
// let upper = mixedCase.uppercaseString // "ABCDEF"
// let lower = mixedCase.lowercaseString // "abcdef"

// Swift 3
let upper = mixedCase.uppercased()       // "ABCDEF"
let lower = mixedCase.lowercased()       // "abcdef"

接下来我还会讲到一些别的命名的变化

使用索引去访问集合

Swift 3 里对于 String 影响最大的一个变化就是 new model for collections and indices. 总结起来就是你不能直接访问 String 里的元素, 而必须使用索引去从集合里把元素取出来:

let country = "España"
country.characters       // characters
country.unicodeScalars   // Unicode scalar 21-bit codes
country.utf16            // UTF-16 encoding
country.utf8             // UTF-8 encoding

Swift 3里每个集合的 view 里的 startIndexendIndex 属性还是没变:

let hello = "hello"
let helloStartIndex = hello.characters.startIndex // 0

如果想要获取字符的集合, 你也可以使用 characters 属性:

(译者注: characters 能够自动帮助我们处理编码问题, 让我们获得人类理解的"字符集合". Swift 的字符串 API 刚接触可能会觉得很难用, 但了解了背后的原理之后, 会发现它其实做了很多, 帮我们避开了很多坑, 了解方法之后也很容易使用)

let startIndex = hello.startIndex // 0
let endIndex = hello.endIndex     // 5
hello[startIndex]                 // "h"

之前通过增减索引去访问字符串的方式改变了, successor(), predecessor()advancedBy(n) 的函数都去掉了.

// Swift 2
hello[hello.startIndex]                // "h"
hello[hello.startIndex.successor()]    // "e"
hello[hello.endIndex.predecessor()]    // "o"
hello[hello.startIndex.advancedBy(2)]  // "l"

现在在 Swift 3 里你会使用 index(after:), index(before:)index(_: offsetBy:) 去处理相同的情况:

// Swift 3
hello[hello.startIndex]                // "h"
hello[hello.index(after: startIndex)]  // "e"
hello[hello.index(before: endIndex)]   // "o"

hello[hello.index(startIndex, offsetBy: 1)]  // "e"
hello[hello.index(endIndex, offsetBy: -4)]   // "e"

你也可以给 offset 加上限制, 避免错误的下标访问. 函数 index(_: offsetBy: limitedBy:) 会返回一个可选值, 下标越界的时候就会返回 nil:

if let someIndex = hello.index(startIndex,
                   offsetBy: 4, limitedBy: endIndex) {
  hello[someIndex] // "o"
}

找到第一个符合条件的元素<T>的方式(在这种情况下, T 是一个字符串):

let matchedIndex = hello.characters.index(of: "l") // 2
let nomatchIndex = hello.characters.index(of: "A") // nil

最后, 获取两个索引之间距离的方法现在也被重新命名了:

// Swift 2
let distance = word1.startIndex.distanceTo(indexC)

// Swift 3
let distance = word1.distance(from: word1.startIndex, to: indexC)

使用 Ranges (范围)

Swift 3 里对 Ranges 进行了修改. 假设我有字符集合的一个起始索引值和一个终点索引值:

let fqdn = "useyourloaf.com"
let tldEndIndex = fqdn.endIndex
let tldStartIndex = fqdn.index(tldEndIndex, offsetBy: -3)

用起始和终点索引去初始化 Range 的方式:

let range = Range(uncheckedBounds: (lower: tldStartIndex, upper: tldEndIndex))
fqdn[range]  // "com"

创建一个范围最简单的方法就是使用 ..<... 操作符:

let endOfDomain = fqdn.index(fqdn.endIndex, offsetBy: -4)
let rangeOfDomain = fqdn.startIndex ..< endOfDomain
fqdn[rangeOfDomain] // useyourloaf

查找和返回子字符串的范围:

if let rangeOfTLD = fqdn.range(of: "com") {
  let tld = fqdn[rangeOfTLD]                 // "com"
}

Playground

你可以在这里找到一份完整的升级后的 API 变化的 playground 文件 Code Examples repository. 我也更新了之前我写的那篇文章 original post.

参考阅读

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 习惯六 统合综效 【统合综效的基本心态是:如果一位具有相当聪明才智的人跟我意见不同,那么对方的主张必定有我尚未体会...
    雪23阅读 204评论 0 0
  • 喜欢的歌就会像自己的孩子一样,容不得别人说她/他的不好。。。。。 我的孩子们呐,一直以来你们都是最能给我安慰的 所...
    顾君一笑阅读 627评论 0 3
  • 我起床了,发现身边睡着一个女人。 她是我的妻子,是杰出的美人也是杰出的生物科学家!能找到她这样的妻子,我很幸福。 ...
    小小小2014阅读 301评论 0 0
  • 《你是我心中的伤》 文/白传英 你现在怎么想 是否和过去一个样 我在你的眼里 没有一次能够顺理成章 ...
    白清风阅读 242评论 0 0