Swift3.0 新的 GCD 和 Core Graphics

来源:互联网 发布:ubuntu睡眠后无法唤醒 编辑:程序博客网 时间:2024/05/16 01:12

DispatchQueue

首先,dispatch 的全局函数不再写为下划线风格的名称了,它变成了一个更符合 Swift 风格的 DispatchQueue 的样子。

main thread

同样的,你不需要在去用 dispatch_get_main_queue ( ) 来获取主线程,而是 DispatchQueue . main ,那么要放到主线程的代码怎么执行呢?只需要在线程后边使用 . async { } 即可,也就是说,大概是这样:

DispatchQueue.main.async { [weak self] in      yourcoderunsin mainthread}

优先级

说完了最基本的东西,我们再来说说其他改变了的东西,比如优先级的名字。

我们知道,GCD 的默认队列优先级有四个:

  • DISPATCH_QUEUE_PRIORITY_HIGH
  • DISPATCH_QUEUE_PRIORITY_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND

现在,新的语法当中,改变了这四个不明不白的优先级名称为更有意义的名字:

  • .userInitialted
  • .default
  • .utility
  • .background

当然,它们的对应关系也就是与顺序相同的:

 DISPATCH_QUEUE_PRIORITY_HIGH:        .userInitiated DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default DISPATCH_QUEUE_PRIORITY_LOW:          .utility DISPATCH_QUEUE_PRIORITY_BACKGROUND:  .background

获取一个队列

我们使用 DispatchQueue . global ( ) 获取一个系统的队列,这样的话获取的就是默认 . default 优先级的队列了,如果要获取其他优先级的队列,就使用 DispatchQueue. global ( qos : . userInitiated ) ,最后,我们使用 . async { } 来执行代码:

 DispatchQueue.global(qos: .userInitiated).async {            //your code here        }

创建一个队列

直接用 DispatchQueue 的初始化器来创建一个队列。最简单直接的办法是这样:

let queue = DispatchQueue(label: "myBackgroundQueue")

复杂一点?你可以指定优先级以及队列类别:

let queue = DispatchQueue(label: "myBackgroundQueue", qos: .userInitiated, attributes: .concurrent)

然后把代码放进去即可:

[php] view plain copy
  1. queue.async {  
  2.     <span class="keyword" style="font-weight:bold">print</span>(<span class="string" style="color:rgb(221,17,68)">"aaa"</span>)  
  3. }  

队列打组

对于组,现在你可以使用这样的语法直接创建一个组:

let group = DispatchGroup()

至于使用,则是这样的:

let group = DispatchGroup() let queue = DispatchQueue(label: "myBackgroundQueue") queue.async(group:group) {    print("background working")}

那么,如果有多个并发队列在同一个组里,我们需要它们完成了再继续呢?

group.wait()

指定时间后执行

很多时候你可能还需要让一些代码在指定的时间后执行,比如动画完成后。这个任务在swift 2.3 很麻烦,不过,在3.0就不一样了:

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) {    print("after!")}

只需要一句话即可。



其他变化: 

升级到 Swift 3

在升级到 Swift 3 时,你会发现,基本上每个文件都需要改动!之所以这样,是因为所有的 Cocoa API 名称都被改变了。简而言之,API 仍然是原来的 API,但这个 API 在 Objective-C 中是一种叫法,而在 Swift 中又是另一种叫法了。Swift 3 语法书写起来要更贴近于自然语言。 
在 Xcode 8 中苹果提供了 Migration Assistant,它可以完成大部分的迁移工作。但很显然,仍然有一部分工作需要你手动完成。 
你可以立即将代码升级到 2.3 或者 3.0。如果你需要将代码又转回来,你可以用 Xcode 的 Edit > Convert > To Current Swift Syntax… 菜单。编译器会和 Migrateion Assistant 一样智能。如果你在调用方法时,偶然使用了老的 API,编译器会显示一个 Fixt-It 选项,让你使用正确的新 API。幸好 Swift 3 在最终发布时,才会停止改变源代码。因此,你可以将你的 Swift 代码保存为不同的版本。但是 Swift 核心团队不能保证这一点以后不会改变,如果在某个时候不在保证源码上的兼容,他们会提供一个较长的过渡期。这意味着源码是稳定的,这样能鼓励更多的保守的公司去使用它。 
这也说明,二进制稳定的目标还没有达到。本文最后将讨论这将导致的影响。

API 的改变

Swift 3 中最大的改变是标准库中在每个库中都采用了统一命名方式。API Design Guidleines中包含了这些规则,核心团队在构建 Swift 3 时采用了这些规则,对新手来说,这高度增强了可读性和易用性。核心团队遵循的是”好的 API 设计应当总是从调用者的角度看待问题“的原则。他们努力让 API 简单易用。不再多说,让我们开始介绍这些对你来说非常重要的改变。

第一个参数的 label

让我们从你每天都会在 Swift 中用到的例子开始。

在函数或方法中的第一个参数现在必须有一个 label ,除非你显式地声明不要。以前,我们调用一个函数或方法时,可以忽略第一个参数的 label[SE-0046]:

<code class="language-swift hljs coffeescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> 第一句是 Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 语法,第二句是 Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> 语法 <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"RW"</span>.writeToFile(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"filename"</span>, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">atomically</span>: <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">true</span>, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">encoding</span>: NSUTF8StringEncoding) <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"RW"</span>.write(<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">toFile</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"filename"</span>, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">atomically</span>: <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">true</span>, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">encoding</span>: NSUTF8StringEncoding) SKAction.rotateByAngle(CGFloat(M_PI_2), <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">duration</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>) SKAction.rotate(<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">byAngle</span>: CGFloat(M_PI_2), <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">duration</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>) UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline) UIFont.preferredFont(<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">forTextStyle</span>: UIFontTextStyleSubheadline) override func numberOfSectionsInTableView<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(tableView: UITableView)</span> -></span> Int override func numberOfSections<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> tableView: UITableView)</span> -></span> Int func viewForZoomingInScrollView<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(scrollView: UIScrollView)</span> -></span> UIView? func viewForZooming<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> scrollView: UIScrollView)</span> -></span> UIView? NSTimer.scheduledTimerWithTimeInterval(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.35</span>, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">target</span>: self, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">selector</span>: <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#selector(reset), userInfo: nil, repeats: true)</span> NSTimer.scheduledTimer(<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">timeInterval</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.35</span>, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">target</span>: self, <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">selector</span>: <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#selector(reset), userInfo: nil, repeats: true)</span> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li></ul>

注意,有些方法使用介词“of”、“to”、“with”、“in”作为外部参数名。这是为了增加代码的可读性。

如果这个方法不使用介词也不使用 label,你应该在方法定义时,显式地在第一个参数名之前加一个下划线:

<code class="language-swift hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> } override func didMoveToView(_ view: SKView) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

在许多编程语言中,许多方法可以共用一个方法名,但参数名不同。Swift 也不例外,现在,你可以重载方法,APIs 能够将直接将它们转换成合适的调用。下面是一个例子,展示了 index() 方法的两种重载形式:

<code class="language-swift hljs fsharp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> names = [<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Anna"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Barbara"</span>] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> annaIndex = names.index(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Anna"</span>) { print(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Barbara's position: \(names.index(after: annaIndex))"</span>) }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

方法名是同一个,但参数名不同,这将让人更容易记忆。

省略不必要的单词

过去,在苹果标准库中,方法名中会包含一个单词,用于表明方法的返回值。因为 Swift 编译支持类型推断,这种做法其实并不必要。核心团队尽可能过滤一切“噪音”,因此将这些重复的单词都删除了,只留下方法名中最重要的部分。

在将 Objective-C 库转换成本地 Swift 语言方面,API 变得更智能了[SE-0005]:

<code class="language-swift hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">// 第一句是 Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 语法,第二句是 Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> 语法 let blue = UIColor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.blueColor</span>() let blue = UIColor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.blue</span> let min = numbers<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.minElement</span>() let min = numbers<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.min</span>() attributedString<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.appendAttributedString</span>(anotherString) attributedString<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.append</span>(anotherString) names<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.insert</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Jane"</span>, atIndex: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) names<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.insert</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Jane"</span>, at: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) UIDevice<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.currentDevice</span>() UIDevice<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.current</span>()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

新的 GCD 和 Core Graphics

一提到遗留下来的“元老级” API,GCG 和 Core Graphics 更需要被重新“装扮一新”。

Grand Central Dispatch 常用于长时间计算或者与服务器通讯。将任务放到不同的线程,你可以避免阻塞用户界面。libdispatch 库是用 C 语言编写的,提供了 C 风格的 API。这个 API 现在在 Swift 中被重新设计为[SE-0088]:

<code class="language-swift hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Swift 2 语法</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">queue</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> dispatch_queue_create(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.test.myqueue"</span>, nil) dispatch_async(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">queue</span>) { print(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Hello World"</span>) } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Swift 3 语法</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">queue</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> DispatchQueue(label: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.test.myqueue"</span>) <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">queue</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>async { print(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Hello World"</span>) }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

类似的情况还有 Core Graphics。Core Graphics 是用 C 编写的,曾经以来一直只能以“丑陋”的函数方式调用。这是它的新的用法[SE-0044]:

<code class="language-swift hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">// Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 语法 let ctx = UIGraphicsGetCurrentContext() let rectangle = CGRect(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">x</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">y</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, width: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>, height: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>) CGContextSetFillColorWithColor(ctx, UIColor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.blueColor</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CGColor</span>) CGContextSetStrokeColorWithColor(ctx, UIColor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.whiteColor</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CGColor</span>) CGContextSetLineWidth(ctx, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>) CGContextAddRect(ctx, rectangle) CGContextDrawPath(ctx, <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.FillStroke</span>) UIGraphicsEndImageContext() // Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> 语法 if let ctx = UIGraphicsGetCurrentContext() { let rectangle = CGRect(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">x</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">y</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, width: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>, height: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>) ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setFillColor</span>(UIColor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.blue</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cgColor</span>) ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStrokeColor</span>(UIColor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.white</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cgColor</span>) ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setLineWidth</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>) ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addRect</span>(rectangle) ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPath</span>(using: <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.fillStroke</span>) UIGraphicsEndImageContext() }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

枚举中 case 值的大小写

另一个和过去的 Swift 代码不同的地方是,在枚举中定义的 case 值现在使用小驼峰命名法。这是为了和属性名或者变量名保持一致[SE-0006]:

<code class="language-swift hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">// 第一句是 Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 语法,第二句是 Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> 语法 UIInterfaceOrientationMask<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Landscape</span> UIInterfaceOrientationMask<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.landscape</span> NSTextAlignment<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Right</span> NSTextAlignment<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.right</span> SKBlendMode<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Multiply</span> SKBlendMode<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.multiply</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

大驼峰命名法现在只在类型名和协议名上使用。当你习惯这一切之后,Swift 团队对于追求一致性的努力才没有白费。

返回值的方法或者修改值的方法

标准库中对方法名中使用动词和名词的规定也更加统一。你应当根据这个方法会导致什么后果或者要采取一些动作来进行方法命名。首要原则是如果这个方法名中包含“ed”或“ing”后缀,则表明这是一个名词。方法名为名词的方法有返回值。如果不包含这些后缀,则很可能这是一个动词。以动词命名的方法会对某块引用的内存进行一些操作。即所谓的“修改某个值”。下面是几个符合名词/动词命名规则的方法[SE-0006]:

<code class="language-swift hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">customArray<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.enumerate</span>() customArray<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.enumerated</span>() customArray<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.reverse</span>() customArray<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.reversed</span>() customArray<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sort</span>() // changed from <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sortInPlace</span>() customArray<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sorted</span>()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

下面是一些使用这些方法的代码片段:

<code class="language-swift hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">var ages = [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">21</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 变量,不是常量,这样你才能修改它</span> ages.<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sort</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 修改值,现在值变成了 [2, 10, 21]</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (index, age) <span class="hljs-operator" style="box-sizing: border-box;">in</span> ages.enumerated() {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // "-ed" 是名词,表示会返回一个 ages 拷贝</span> print(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\(index). \(age)"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 打印:1. 2 \n 2. 10 \n 3. 21</span> } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">###函数类型</span> 函数在声明和调用时,都需要用括号将参数括住: ```swift func f(<span class="hljs-operator" style="box-sizing: border-box;">a</span>: Int) { ... } f(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>) <<span class="hljs-operator" style="box-sizing: border-box;">div</span> class=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span>></<span class="hljs-operator" style="box-sizing: border-box;">div</span>> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

但是,当你用函数类型作为参数时,你可能会写出这样的代码:

<code class="language-swift hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">func g(a: Int -> Int) -> Int -> Int { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> } // Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 语法 <div class=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span>></div> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

你会发现代码很难读懂。参数在哪里结束,返回值从哪里开始?在 Swift 3 中,正确的定义方法是[SE-0066]:

<code class="language-swift hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">func g(a: (Int) -> Int) -> (Int) -> Int { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> } // new way, Swift <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <div class=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span>></div> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

现在,参数列表被括号包裹,然后才是返回类型。事情变得简单,同时函数类型更容易被识别出来。通过下面的比照,你会更清楚:

<code class="language-swift hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Swift 2 语法</span> Int <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>Float <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>Int T <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>U Int <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>Float <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Swift 3 语法</span> (Int) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>Float (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>Int (T) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>U (Int) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span>(Float) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-> </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>div class<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">><</span>/div<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

API 的增强

除了对已有 API 进行“旧瓶新装”这个最大的改变以外——有非常多的 Swift 社区正致力于此,也有对 Swift API 的一些功能上的增加。

访问所属类型

当你定义一个静态属性或方法时,你直接通过类或类型来调用它们:

<code class="language-swift hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">CustomStruct.staticMethod() <<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">div</span> <span class="hljs-type" style="box-sizing: border-box;">class</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span>></<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">div</span>> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

如果你当前正在编写类型内部的代码,你还是要使用类型名来调用静态方法。为了使表述更加清晰,现在你可以通过 Self 来引用当前实例所属类型。S 为大写的 Self 表示引用当前实例的类型,而 s 为小写的 self 则引用当前实例自身。

这是具体的例子[SE-0068]:

<code class="language-swift hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">struct CustomStruct { static func staticMethod() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> } func instanceMethod() { Self.staticMethod() // 在类型内部 } } let customStruct = CustomStruct() customStruct.Self.staticMethod() // 在一个实例上应用类型 <div class=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span>></div> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

行内 Sequences

sequence(first:next:) 以及 sequence(state:next:) 是全局函数,返回一个无限序列。你传给它们一个初值或一个可变的状态,它们会在稍后调用闭包中的代码[SE-0094]:

<code class="language-swift hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> view <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> sequence(first: someView, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">next</span>: { $<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.</span>superview }) { // someView, someView.superview, someView.superview.superview, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> } <div class=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"se-preview-section-delimiter"</span>></div> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

还可以用 prefix 操作符来为序列加一个限制[SE-0045]:

<code class="language-swift hljs mel has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> x <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> sequence(first: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.1</span>, next: { <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$0</span> * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> }).prefix(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>: { <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$0</span> < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> }) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 0.1, 0.2, 0.4, 0.8, 1.6, 3.2</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

杂项

  • #keyPath() 等同于 #selector() ,帮助你减少输入错误
  • 你可以在某些类型上调用 pi,比如:Float.pi、CGFloat.pi。大部分时候编译器能够推断出类型:let circumference = 2 * .pi * radius [SE-0067]
  • NS 前缀从老的 Foundation 类型中移除,现在可以用 Calendar、Date来替代 NSCalendar、NSDate 了

工具的改善

Swift 只是一门语言,大部分时候你都无法离开书写它的开发环境——对于苹果开发者来说,也就是 Xcode!工具上的改变影响着每天编写代码的方式。 
Swift 3 修正了编译器和 IDE 中的 Bug,还改善了报告错误和信息的精确性。就像你所期望的,每个版本的发布都会让 Swift 和编译器的运行变得更快:

  • 改善了字符串的 Hash 算法,导致在将字符串存入字典后,性能有 3 倍的提升
  • 将对象从堆移到栈中存放,导致性能有 24 倍的提升(某些情况下)
  • 编译器可以一次缓存多个文件(在整个模块被优化过的情况下)
  • 优化了代码的大小,导致 Swift 代码的编译尺寸更小。以苹果的 Demobots 为例,编译尺寸缩减了原大小的 77%。

Xcode 也会更加智能地理解 Swift 代码:

  • 过去,当你在一个 API 方法比如 sort() 上右击并跳转到定义时,你会看到一个不太容易理解的头文件。现在,在 Xcode 8 中,你会看到 sort() 方法实际上是 Array 类的扩展。

1 0
原创粉丝点击