Merge remote-tracking branch 'numbbbbb/gh-pages' into develop

This commit is contained in:
Qing
2015-10-23 07:39:35 +08:00
25 changed files with 729 additions and 657 deletions

View File

@ -25,15 +25,13 @@
我错了。
![](https://raw.githubusercontent.com/numbbbbb/the-swift-programming-language-in-chinese/gh-pages/swift%202.0%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/1.png)
![1](https://cloud.githubusercontent.com/assets/1472352/10558349/74eb84de-74fe-11e5-99d2-155dfacff068.png)
![2](https://cloud.githubusercontent.com/assets/1472352/10558351/79101476-74fe-11e5-82d5-feb815d0b86b.png)
![3](https://cloud.githubusercontent.com/assets/1472352/10558353/7c983272-74fe-11e5-8397-97c5176261ca.png)
![4](https://cloud.githubusercontent.com/assets/1472352/10558354/7cd63ae0-74fe-11e5-9b9d-1d7ec6516319.png)
![5](https://cloud.githubusercontent.com/assets/1472352/10558358/7fe50914-74fe-11e5-9b2b-a7b9129ea638.png)
![6](https://cloud.githubusercontent.com/assets/1472352/10558360/83a8b064-74fe-11e5-9c2f-2e79d3309f62.png)
![](https://raw.githubusercontent.com/numbbbbb/the-swift-programming-language-in-chinese/gh-pages/swift%202.0%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/2.png)
![](https://raw.githubusercontent.com/numbbbbb/the-swift-programming-language-in-chinese/gh-pages/swift%202.0%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/3.png)
![](https://raw.githubusercontent.com/numbbbbb/the-swift-programming-language-in-chinese/gh-pages/swift%202.0%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/4.png)
![](https://raw.githubusercontent.com/numbbbbb/the-swift-programming-language-in-chinese/gh-pages/swift%202.0%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/5.png)
在我没有任何回复的情况下,不到一天时间,有五位朋友报名。看到这些回复的时候我真的很惊讶,也很感动,无论这个项目存在多少问题,只要有人关注,有人愿意为它付出,那我还有什么理由放弃呢?
@ -75,4 +73,4 @@ Swift 2.0 参与者名单(按照章节顺序):
- [wardenNScaiyi](https://github.com/wardenNScaiyi)
- [miaosiqi](https://github.com/miaosiqi)
最后,感谢<a target='_blank' href="http://wiki.jikexueyuan.com/">极客学院</a>提供的wiki系统在国内访问起来速度很快优化后的样式看起来也更舒服。
最后,感谢[极客学院](http://wiki.jikexueyuan.com)提供的wiki系统在国内访问起来速度很快优化后的样式看起来也更舒服。

View File

@ -233,7 +233,7 @@ print(secondForLoop)
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
greet("Bob", day: "Tuesday")
```
> 练习:

View File

@ -44,7 +44,7 @@
<tr>
<td scope="row">2015-04-13</td>
<td><ul class="list-bullet">
<li><p>
<li>
XCode6.4包含了对于构建和调试基于iOS8.4 App的支持
</li>
</ul>
@ -68,46 +68,47 @@
<tr>
<td scope="row">2015-4-8</td>
<td><ul class="list-bullet">
<li><p>
Swift现在自身提供了一个<code>Set</code>集合类型,更多信息请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID484">集合</a>
<li>
Swift现在自身提供了一个<code>Set</code>集合类型,更多信息请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID484">集合</a>
</li>
<li><p>
<li>
<code>@autoclosure</code>现在是一个参数声明的属性,而不是参数类型的属性。这里还有一个新的参数声明属性<code>@noescape</code>。更多信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-ID348">属性声明</a>
</li>
<li><p>
<li>
对于类型属性和方法现在可以使用<code>static</code>关键字作为声明描述符,更多信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID483">类型变量属性</a>
</li>
<li><p>
<li>
Swift现在包含一个<code>as?</code><code>as!</code>的向下可失败类型转换运算符。更多信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID283">协议遵循性检查</a>
</li>
<li><p>
<li>
增加了一个新的指导章节,它是关于<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID495">字符串索引</a>
</li>
<li><p>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID37">溢出运算符</a>中移除了溢出除运算符(<code>&/</code>)和求余溢出运算符(<code>&%</code>)
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID37">溢出运算符</a>中移除了溢出除运算符和求余溢出运算符
</li>
<li><p>
<li>
更新了常量和常量属性在声明和构造时的规则,更多信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID355">常量声明</a>
</li>
<li><p>
<li>
更新了字符串字面量中Unicode标量集的定义请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID295">字符串字面量中的特殊字符</a>
</li>
<li><p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID73">区间运算符</a>章节来提示当半开区间运算符含有相同的起止索引时,其区间为空。
</li>
<li><p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID104">闭包引用类型</a>章节来澄清对于变量的捕获规则
</li>
<li><p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID38">值溢出</a>章节来澄清有符号整数和无符号整数的溢出行为
</li>
<li><p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID369">协议声明</a>章节来澄清协议声明时的作用域和成员
</li>
<li><p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID58">捕获列表</a>章节来澄清对于闭包捕获列表中的弱引用和无主引用的使用语法。
</li>
<li><p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID418">运算符</a>章节来明确指明一些例子来说明自定义运算符所支持的特性如数学运算符各种符号Unicode符号块等
</li>
</ul>
@ -132,23 +133,23 @@
<tr>
<td scope="row">2015-02-09</td>
<td><ul class="list-bullet">
<li><p>
<li>
在函数作用域中的常量声明时可以不被初始化,它必须在第一次使用前被赋值。更多的信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID355">常量声明</a>
</li>
<li><p>
<li>
在构造器中,常量属性有且仅能被赋值一次。更多信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID212">在构造过程中给常量属性赋值</a>
</li>
<li><p>
<li>
多个可选绑定现在可以在<code>if</code>语句后面以逗号分隔的赋值列表的方式出现,更多信息,请看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID333">可选绑定</a>
</li>
<li><p>
<li>
一个<a link="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID405">可选链表达式</a>必须出现在后缀表达式中
</li>
<li><p>
<li>
协议类型转换不再局限于<code>@obj</code>修饰的协议了
</li>
<li><p>
在运行时可能会失败的类型转换可以使用<code>as?</code><code>as!</code>运算符,而确保不会失败的类型转换现在使用<code>as</code>运算符。更多信息,请看<a link="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID388">类型转换运算符</a>
<li>
在运行时可能会失败的类型转换可以使用<code>as?</code><code>as!</code>运算符,而确保不会失败的类型转换现在使用<code>as</code>运算符。更多信息,请看<a link="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID388">类型转换运算符</a>
</li>
</ul>
</td>
@ -171,17 +172,18 @@
<tbody>
<tr>
<td scope="row">2014-12-19</td>
<td><ul class="list-bullet">
<li><p>
<td>
<ul class="list-bullet">
<li>
在对Watch App做消息通知模拟调试时第一个payload.apns文件将会被默认选择
</li>
<li><p>
<li>
在为Watch App使用asset catalog时38mm和42mm尺寸的图片就会被使用
</li>
<li><p>
<li>
在做Watch App开发时,<code>@IBAction</code>属性支持<code>WKInterfaceSwitch</code><code>WKInterfaceSlider</code> Swift类型了
</li>
<li><p>
<li>
现在可以通过Device窗口安装删除和访问App容器中的数据了。
</li>
</ul>
@ -206,7 +208,7 @@
<tr>
<td scope="row">2014-12-10</td>
<td><ul class="list-bullet">
<li><p>
<li>
现在在Interface Builder中可以针对特定的Device设备自定义Watch应用的Layout布局了
</li>
</ul>
@ -231,16 +233,16 @@
<tr>
<td scope="row">2014-11-28</td>
<td><ul class="list-bullet">
<li><p>
<li>
XCode6.2包含了iOS8.2 SDK该SDK中包含WatchKit用来开发Apple Watch应用。
</li>
<li><p>
<li>
在工具集中增加了对WatchKit的支持
1UI设计工具增加了Apple Watch应用的界面组件通知和小部件。
2增加了调试和性能统计功能
3增加Apple Watch应用的模拟器帮助调试应用功能
</li>
<li><p>
<li>
为了使Apple Watch应用能够正常工作一些具体的参数必须设置
1WatchKit中扩展配置文件Info.plist中的<code>NSExtensionAttributes</code>配置项WKAppBundleIdentifier必须和WatchKit App中的通用配置文件中的属性<code>CFBundleIdentifier</code>项目保持一致。2WatchKit中的<code>CFBundleIdentifier</code>配置项必须和<code>WKCompanionAppBundleIdentifier</code>中的配置项保持一致
</li>
@ -266,16 +268,16 @@
<tr>
<td scope="row">2014-12-2</td>
<td><ul class="list-bullet">
<li><p>
<li>
在SourceKit中一些导致Crash的常见问题被修复比如名字冲突和遗留废弃数据的问题等。
</li>
<li><p>
<li>
把纯正的Swift类对象实例赋值给AnyObject量不会再Crash了。
</li>
<li><p>
<li>
在泛型使用场景下,遵循了协议类要求的构造器方法或者类型方法可以直接调用继承类中的方法了。
</li>
<li><p>
<li>
修正了InterfaceBuild中如果图片名字含有“/”时会在OSX10.10上Crash或者无法打开的问题
</li>
</ul>
@ -300,13 +302,13 @@
<tr>
<td scope="row">2014-10-16</td>
<td><ul class="list-bullet">
<li><p>
<li>
增加了一个完整的关于<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html">失败构造器(Failable Initializers)</a>的指南文档
</li>
<li><p>
<li>
增加了一个关于协议的<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html">失败构造器需求(Failable Initializer Requirements)</a>的描述
</li>
<li><p>
<li>
`Any`类型的常量或变量现在可以包含一个函数实例了。同时更新了<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html">`Any`</a>章节的案例用来演示如何在swith语句中检查和转换一个函数类型。
</li>
</ul>
@ -331,7 +333,7 @@
<tr>
<td scope="row">2014-09-15</td>
<td><ul class="list-bullet">
<li><p>
<li>
带有原始值的枚举类型增加了一个<code>rawValue</code>属性替代<code>toRaw()</code>方法,同时使用了一个以<code>rawValue</code>为参数的失败构造器来替代<code>fromRaw()</code>方法。更多的信息,请看<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html">原始值(Raw Values)</a><a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html">带原始值的枚举类型(Enumerations with Cases of a Raw-Value Type)</a>部分
</li>
</ul>
@ -356,10 +358,10 @@
<tr>
<td scope="row">2014-09-09</td>
<td><ul class="list-bullet">
<li><p>
<li>
增加了一个新的关于<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html">失败构造器(Failable Initializers)</a>的参考章节,失败构造器可以触发失败的构造过程
</li>
<li><p>
<li>
自定义运算符现在可以包含`?`字符,更新的<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html">运算符(Operators)</a>章节描述了改进后的规则,并且从<a href="http://developer.apple.com/library/etc/redirect/xcode/devtools/419f35/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html">自定义运算符(Custom Operators)</a>章节删除了重复的运算符有效字符集合
</li>
</ul>
@ -384,18 +386,19 @@
<tr>
<td scope="row">2014-09-03</td>
<td><ul class="list-bullet">
<li><p>
<li>
实现了内部库的修改和适配,主要包括如下:
1大量内部类或者函数遵循Optional类型和协议
2移除大部分函数返回类型隐式解封可选类型的使用
</li>
<li><p>
<li>
对于泛型的类库函数或接口统一从<code>T!</code>更换为<code>T</code><code>T</code>,这样使得语法更加严谨,明确了可能返回为空和不为空的情况
</li>
<li><p>
<li>
字符类型不能使用+运算法链接,可以以<code>String(C1)+String(2)</code> 的方式实现字符间链接
</li>
<li><p>
<li>
重写了<code>Sort</code>函数,解决了栈溢出的问题
</li>
</ul>
@ -418,20 +421,20 @@
<tr>
<td scope="row">2014-08-18</td>
<td><ul class="list-bullet">
<li><p>
在章节协议中,增加新的小节:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_397">对构造器的规定Initializer Requirements</a></p>
<li>
在章节协议中,增加新的小节:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_397">对构造器的规定Initializer Requirements</a>
</li>
<li><p>
在章节协议中,增加新的小节:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_409">类专属协议class-only protocols</a></p>
<li>
在章节协议中,增加新的小节:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_409">类专属协议class-only protocols</a>
</li>
<li><p>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_494">断言(assertions)</a>现在可以使用字符串内插语法,并删除了文档中有冲突的注释</p>
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_494">断言(assertions)</a>现在可以使用字符串内插语法,并删除了文档中有冲突的注释
</li>
<li><p>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_428">连接字符串和字符Concatenating Strings and Characters</a>小节来说明一个事实,那就是字符串和字符不能再用<code>+</code>号运算符或者复合加法运算符<code>+=</code>相互连接,这两种运算符现在只能用于字符串之间相连。请使用<code>String</code>类型的<code>append</code>方法在一个字符串的尾部增加单个字符</p>
<li>
更新了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_428">连接字符串和字符Concatenating Strings and Characters</a>小节来说明一个事实,那就是字符串和字符不能再用<code>+</code>号运算符或者复合加法运算符<code>+=</code>相互连接,这两种运算符现在只能用于字符串之间相连。请使用<code>String</code>类型的<code>append</code>方法在一个字符串的尾部增加单个字符
</li>
<li><p>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-XID_516">声明特性Declaration Attributes</a>章节增加了关于<code>availability</code>特性的一些信息</p>
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-XID_516">声明特性Declaration Attributes</a>章节增加了关于<code>availability</code>特性的一些信息
</li>
</ul>
</td>
@ -453,58 +456,58 @@
<tr>
<td scope="row">2014-08-04</td>
<td><ul class="list-bullet">
<li><p>
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_478">可选类型Optionals</a> 若有值时,不再隐式的转换为 <code>true</code>,同样,若无值时,也不再隐式的转换为 <code>false</code>, 这是为了避免在判别 optional <code>Bool</code> 的值时产生困惑。 替代的方案是,用<code>==</code><code>!=</code> 运算符显式地去判断Optinal是否是 <code>nil</code>,以确认其是否包含值。
</li>
<li><p>
<li>
Swift新增了一个 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_124" data-id="//apple_ref/doc/uid/TP40014097-CH6-XID_124">Nil合并运算符Nil Coalescing Operator</a> (<code>a ?? b</code>), 该表达式中如果Optional <code>a</code>的值存在则取得它并返回若Optional <code>a</code><code>nil</code>,则返回默认值 <code>b</code>
</li>
<li><p>
<li>
更新和扩展 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_434">字符串的比较Comparing Strings</a> 章节,用以反映和展示'字符串和字符的比较',以及'前缀prefix/后缀(postfix)比较'都开始基于扩展字符集(extended grapheme clusters)规范的等价比较.
</li>
<li><p>
<li>
现在,你可以通过 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html#//apple_ref/doc/uid/TP40014097-CH21-XID_356">可选链Optional Chaining</a>给属性设值将其赋给一个下标脚注subscript; 或调用一个变异mutating方法或运算符。对此章节——<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html#//apple_ref/doc/uid/TP40014097-CH21-XID_364">通过可选链访问属性Accessing Properties Through Optional Chaining</a>的内容已经被相应的更新。而章节——<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html#//apple_ref/doc/uid/TP40014097-CH21-XID_361">通过可选链调用方法Calling Methods Through Optional Chaining</a>中,关于检查方法调用是否成功的例子,已被扩展为展示如何检查一个属性是否被设值成功。
</li>
<li><p>
<li>
在章节可选链中,增加一个新的小节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html#//apple_ref/doc/uid/TP40014097-CH21-XID_364">访问可选类型的下标脚注Accessing Subscripts of Optional Type</a>
</li>
<li><p>
<li>
更新章节 <a href="CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_176" data-id="//apple_ref/doc/uid/TP40014097-CH8-XID_176">访问和修改数组(Accessing and Modifying an Array)</a> 以标示:从该版本起,不能再通过<code>+=</code> 运算符给一个数组添加一个新的项。. 对应的替代方案是, 使<code>append</code> 方法, 或者通过<code>+=</code>运算符来添加一个<b>只有一个项的数组</b>single-item Array.</li>
<li><p>
<li>
添加了一个提示:在 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_126">范围运算符Range Operators</a>中,比如, <code>a...b</code><code>a..&lt;b</code> ,起始值<code>a</code>不能大于结束值<code>b</code>.
</li>
<li><p>
<li>
重写了<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_293">继承Inheritance</a> 这一章删除了本章中关于构造器重写的介绍性报道转而将更多的注意力放到新增的部分——子类的新功能以及如何通过重写overrides修改已有的功能。另外小节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_301">重写属性的Getters和SettersOverriding Property Getters and Setters</a> 中的例子已经被替换为展示如何重写一个 <code>description</code> 属性. (而关于如何在子类的构造器中修改继承属性的默认值的例子,已经被移到 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_293">构造过程Initialization</a> 这一章.)
</li>
<li><p>
<li>
更新了 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_331">构造器的继承与重写Initializer Inheritance and Overriding</a> 小节以标示: 重写一个特定的构造器必须使用 <code>override</code> 修饰符.
</li>
<li><p>
<li>
更新 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_339"> Required构造器Required Initializers</a> 小节以标示:<code>required</code> 修饰符现在需要出现在所有子类的required构造器的声明中, 而required构造器的实现现在可以仅从父类自动继承。
</li>
<li><p>
<li>
中置Infix<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_80">运算符函数Operator Functions</a> 不再需要<code>@infix</code> 属性.
</li>
<li><p>
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/RevisionHistory.html#//apple_ref/doc/uid/TP40014097-CH40-XID_1631">前置和后置运算符(Prefix and Postfix Operators)</a><code>@prefix</code><code>@postfix</code> 属性,已变更为 <code>prefix</code><code>postfix</code> 声明修饰符declaration modifiers.
</li>
<li><p>
<li>
增加一条注解当Prefix和postfix运算符被作用于同一个操作数时关于<a href="AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_81" data-id="//apple_ref/doc/uid/TP40014097-CH27-XID_81">前置和后置运算符(Prefix and Postfix Operators)</a>的顺序(postfix运算符会先被执行)
</li>
<li><p>
<li>
在运算符函数Operator functions <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_82" data-id="//apple_ref/doc/uid/TP40014097-CH27-XID_82">组合赋值运算符Compound Assignment Operators</a> 不再使用 <code>@assignment</code> 属性来定义函数.
</li>
<li><p>
<li>
在这个版本中,在定义<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_85">自定义操作符Custom Operators</a> 时,<b>修饰符Modifiers的出现顺序发生变化</b>。比如, 现在,你该编写 <code>prefix operator</code> 而不是 <code>operator prefix</code>.
</li>
<li><p>
<li>
增加信息:关于<code>dynamic</code> 声明修饰符declaration modifier于章节 <a href="Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_705" data-id="//apple_ref/doc/uid/TP40014097-CH34-XID_705">声明修饰符Declaration Modifiers</a>.
</li>
<li><p>
<li>
增加信息:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_886">字面量Literals</a> 的类型推导type inference
</li>
<li><p>
<li>
为章节<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_597">Curried Functions</a>添加了更多的信息.
</li>
</ul>
@ -527,49 +530,49 @@
<tr>
<td scope="row">2014-07-21</td>
<td><ul class="list-bullet">
<li><p>
加入新的章节 <a href=https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html#//apple_ref/doc/uid/TP40014097-CH41-XID_29">权限控制Access Control</a>.
<li>
加入新的章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html#//apple_ref/doc/uid/TP40014097-CH41-XID_29">权限控制Access Control</a>.
</li>
<li><p>
<li>
更新了章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_413">字符串和字符Strings and Characters</a> 用以表明在Swift中<code>Character</code> 类型现在代表的是扩展字符集(extended grapheme cluster)中的一个Unicode为此新增了小节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_431">Extended Grapheme Clusters</a> 。同时,为小节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_428">Unicode标量Unicode Scalars</a><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_434">字符串比较Comparing Strings</a>增加了更多内容.
</li>
<li><p>
<li>
更新章节<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_856">字符串字面量String Literals</a>在一个字符串中Unicode标量Unicode scalars<code>\u{n}</code>的形式来表示, <code>n</code> 是一个最大可以有8位的16进制数hexadecimal digits
</li>
<li><p>
<code>NSString</code> <code>length</code> 属性已被映射到Swift的内建 <code>String</code>类型。(注意,这两属性的类型是<code>utf16<color="red">C</color>ount</code>,而非 <code>utf16count</code>.
<li>
<code>NSString</code> <code>length</code> 属性已被映射到Swift的内建 <code>String</code>类型。(注意,这两属性的类型是<code>utf16Count</code>,而非 <code>utf16count</code>.
</li>
<li><p>
<li>
Swift的内建 <code>String</code> 类型不再拥有 <code>uppercaseString</code><code>lowercaseString</code> 属性.其对应部分在章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_413">字符串和字符Strings and Characters</a>已经被删除, 并且各种对应的代码用例也已被更新.
</li>
<li><p>
<li>
加入新的章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_315">没有外部名的构造器参数Initializer Parameters Without External Names</a>.
</li>
<li><p>
<li>
加入新的章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_339"> Required构造器Required Initializers</a>.
</li>
<li><p>
<li>
加入新的章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-XID_252">可选元祖(函数)返回类型 Optional Tuple Return Types</a>.
</li>
<li><p>
<li>
更新章节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_453">类型标注Type Annotations</a> 多个相关变量可以用“类型标注”type annotaion在同一行中声明为同一类型。
</li>
<li><p>
<li>
<code>@optional</code>, <code>@lazy</code>, <code>@final</code>, <code>@required</code> 等关键字被更新为 <code>optional</code>, <code>lazy</code>, <code>final</code>, <code>required</code> <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_705">参见声明修饰符Declaration Modifiers</a>.
</li>
<li><p>
<li>
更新整本书 —— 引用 <code>..&lt;</code> 作为<a href="BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_128" data-id="//apple_ref/doc/uid/TP40014097-CH6-XID_128">区间运算符Half-Open Range Operator</a> (取代原先的<code>..</code> ).
</li>
<li><p>
<li>
更新了小节 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_185">读取和修改字典Accessing and Modifying a Dictionary</a> <code>Dictionary</code> 现在早呢更加了一个 Boolean型的属性 <code>isEmpty</code>
</li>
<li><p>
<li>
解释了哪些字符(集)可被用来定义<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_85">自定义操作符 Custom Operators</a>
</li>
<li><p>
<li>
<code>nil</code> 和布尔运算中的 <code>true</code><code>false</code> 现在被定义为字面量<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_886">Literals</a>.
</li>
</ul></td>
</ul>
</td>
</tr>
</tbody>
@ -589,30 +592,31 @@
<tr>
<td scope="row">2014-07-7</td>
<td><ul class="list-bullet">
<li><p>
<li>
Swift 中的数组 <code>Array</code> 类型从现在起具备了完整的值语义。具体信息被更新到 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_170">集合的可变性Mutability of Collections</a><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_172">数组Arrays</a> 两小节,以反映这个新的变化. 此外,还解释了如何 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_150">给Strings, Arrays和Dictionaries进行赋值和拷贝 Assignment and Copy Behavior for Strings, Arrays, and Dictionaries</a>.
</li>
<li><p>
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_173">数组类型速记语法Array Type Shorthand Syntax</a><code>SomeType[]</code>.更新为<code>[SomeType]</code>
</li>
<li><p>
<li>
加入新的小节:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_182">字典类型的速记语法Dictionary Type Shorthand Syntax)</a>. <code>[KeyType: ValueType]</code>.
</li>
<li><p>
<li>
加入新的小节:<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_189">字典键类型的哈希值Hash Values for Dictionary Key Types)</a>.
</li>
<li><p>
<li>
例子 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-XID_154">闭包表达式 (Closure Expressions)</a> 中使用新的全局函数 <code>sorted</code> 取代原先的全局函数 <code>sort</code> 去展示如何返回一个全新的数组.
</li>
<li><p>
<li>
更新关于 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_320">结构体逐一成员构造器 Memberwise Initializers for Structure Types</a> 的描述:即使结构体的成员<b>没有默认值</b>,逐一成员构造器也可以自动获得。
</li>
<li><p>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_128">区间运算符Half-Open Range Operator</a><code>..</code>更新到<code>..<</code><p>
<li><p>
<li>
<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_128">区间运算符Half-Open Range Operator</a><code>..</code>更新到<code>..&lt;</code>
</li>
<li>
添加一个例子 <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-XID_285">扩展一个泛型Extending a Generic Type</a>
</li>
</ul></td>
</ul>
</td>
</tr>
</tbody>
@ -632,9 +636,10 @@
<tr>
<td scope="row">2014-07-7</td>
<td><ul class="list-bullet">
<li><p>
<li>
发布新的文档用以详述Swift - 苹果公司针对iOS和OS X应用的全新开发语言
</li>
</ul>
</td>
</tr>
</tbody>
@ -654,11 +659,11 @@
<tr>
<td scope="row">2014-06-3</td>
<td><ul class="list-bullet">
<li><p>
<li>
苹果全球开发者大会WWDC2014召开发布了苹果最新的开发语言Swift并释放出XCode6 Beta1版本
</li>
</ul>
</td>
</tr>
</tbody>
</table>

Binary file not shown.

View File

@ -7,6 +7,7 @@
> 2.0
> 翻译+校对:[xtymichael](https://github.com/xtymichael)
> 定稿:[shanks](http://codebuild.me)
本页包含内容:
@ -67,7 +68,7 @@ var currentLoginAttempt = 0
这两行代码可以被理解为:
“声明一个名字是`maximumNumberOfLoginAttempts`的新常量,并给它一个值`10`。然后,声明一个名字是`currentLoginAttempt`的变量并将它的值初始化为`0`.
“声明一个名字是`maximumNumberOfLoginAttempts`的新常量,并给它一个值`10`。然后,声明一个名字是`currentLoginAttempt`的变量并将它的值初始化为`0`
在这个例子中,允许的最大尝试登录次数被声明为一个常量,因为这个值不会改变。当前尝试登录次数被声明为一个变量,因为每次尝试登录失败的时候都需要增加这个值。
@ -259,11 +260,11 @@ Swift 也提供了一个特殊的无符号类型`UInt`,长度与当前平台
<a name="type_safety_and_type_inference"></a>
## 类型安全和类型推断
Swift 是一个类型安全type safe的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。如果你的代码需要一个`String`,你绝对不可能不小心传进去一个`Int`。
Swift 是一个*类型安全type safe*的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。如果你的代码需要一个`String`,你绝对不可能不小心传进去一个`Int`。
由于 Swift 是类型安全的所以它会在编译你的代码时进行类型检查type checks并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。
由于 Swift 是类型安全的,所以它会在编译你的代码时进行*类型检查type checks*,并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。
当你要处理不同类型的值时类型检查可以帮你避免错误。然而这并不是说你每次声明常量和变量的时候都需要显式指定类型。如果你没有显式指定类型Swift 会使用_类型推断_type inference来选择合适的类型。有了类型推断编译器可以在编译代码的时候自动推断出表达式的类型。原理很简单只要检查你赋的值即可。
当你要处理不同类型的值时类型检查可以帮你避免错误。然而这并不是说你每次声明常量和变量的时候都需要显式指定类型。如果你没有显式指定类型Swift 会使用*类型推断type inference*来选择合适的类型。有了类型推断,编译器可以在编译代码的时候自动推断出表达式的类型。原理很简单,只要检查你赋的值即可。
因为有类型推断,和 C 或者 Objective-C 比起来 Swift 很少需要声明类型。常量和变量虽然需要明确类型,但是大部分工作并不需要你自己来完成。
@ -299,10 +300,10 @@ let anotherPi = 3 + 0.14159
整数字面量可以被写作:
* 一个十进制数,没有前缀
* 一个二进制数,前缀是`0b`
* 一个八进制数,前缀是`0o`
* 一个十六进制数,前缀是`0x`
* 一个*十进制*数,没有前缀
* 一个*二进制*数,前缀是`0b`
* 一个*八进制*数,前缀是`0o`
* 一个*十六进制*数,前缀是`0x`
下面的所有整数字面量的十进制值都是`17`:
@ -468,9 +469,9 @@ if i == 1 {
<a name="tuples"></a>
## 元组
元组tuples把多个值组合成一个复合值。元组内的值可以是任意类型并不要求是相同类型。
*元组tuples*把多个值组合成一个复合值。元组内的值可以是任意类型,并不要求是相同类型。
下面这个例子中,`(404, "Not Found")`是一个描述 HTTP 状态码HTTP status code的元组。HTTP 状态码是当你请求网页的时候 web 服务器返回的一个特殊值。如果你请求的网页不存在就会返回一个`404 Not Found`状态码。
下面这个例子中,`(404, "Not Found")`是一个描述 *HTTP 状态码HTTP status code*的元组。HTTP 状态码是当你请求网页的时候 web 服务器返回的一个特殊值。如果你请求的网页不存在就会返回一个`404 Not Found`状态码。
```swift
let http404Error = (404, "Not Found")
@ -531,7 +532,7 @@ print("The status message is \(http200Status.description)")
<a name="optionals"></a>
## 可选类型
使用可选类型optionals来处理值可能缺失的情况。可选类型表示
使用*可选类型optionals*来处理值可能缺失的情况。可选类型表示:
* 有值,等于 x
@ -552,7 +553,7 @@ let convertedNumber = Int(possibleNumber)
// convertedNumber 被推测为类型 "Int?" 或者类型 "optional Int"
```
因为该构造器可能会失败所以它返回一个_可选类型_optional`Int`,而不是一个`Int`。一个可选的`Int`被写作`Int?`而不是`Int`。问号暗示包含的值是可选类型,也就是说可能包含`Int`值也可能不包含值。(不能包含其他任何值比如`Bool`值或者`String`值。只能是`Int`或者什么都没有。)
因为该构造器可能会失败所以它返回一个_可选类型_optional`Int`,而不是一个`Int`。一个可选的`Int`被写作`Int?`而不是`Int`。问号暗示包含的值是可选类型,也就是说可能包含`Int`值也可能*不包含值*。(不能包含其他任何值比如`Bool`值或者`String`值。只能是`Int`或者什么都没有。)
<a name="nil"></a>
### nil
@ -592,7 +593,7 @@ if convertedNumber != nil {
}
// 输出 "convertedNumber contains some integer value."
```
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(`!`来获取值。这个惊叹号表示“我知道这个可选有值请使用它。”这被称为可选值的_强制解析_forced unwrapping
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(`!`来获取值。这个惊叹号表示“我知道这个可选有值请使用它。”这被称为可选值的_强制解析forced unwrapping_
```swift
if convertedNumber != nil {
@ -609,7 +610,7 @@ if convertedNumber != nil {
<a name="optional_binding"></a>
### 可选绑定
使用可选绑定optional binding来判断可选类型是否包含值如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在`if`和`while`语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。`if`和`while`语句,请参考[控制流](./05_Control_Flow.html)。
使用*可选绑定optional binding*来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在`if`和`while`语句中,这条语句不仅可以用来判断可选类型中是否有值,同时可以将可选类型中的值赋给一个常量或者变量。`if`和`while`语句,请参考[控制流](./05_Control_Flow.html)。
像下面这样在`if`语句中写一个可选绑定:
@ -619,7 +620,7 @@ if let constantName = someOptional {
}
```
你可以像上面这样使用可选绑定来重写`possibleNumber`这个例子:
你可以像上面这样使用可选绑定来重写`possibleNumber`这个[例子](./01_The_Basics.html#optionals)
```swift
if let actualNumber = Int(possibleNumber) {
@ -696,7 +697,7 @@ if let definiteString = assumedString {
<a name="error_handling"></a>
## 错误处理
你可以使用错误处理(error handling)来应对程序执行中可能会遇到的错误条件。
你可以使用*错误处理error handling*来应对程序执行中可能会遇到的错误条件。
相对于可选中运用值的存在与缺失来表达函数的成功与失败,错误处理可以推断失败的原因,并传播至程序的其他部分。
@ -747,7 +748,7 @@ do {
<a name="assertions"></a>
## 断言
可选类型可以让你判断值是否存在你可以在代码中优雅地处理值缺失的情况。然而在某些情况下如果值缺失或者值并不满足特定的条件你的代码可能没办法继续执行。这时你可以在你的代码中触发一个断言assertion来结束代码运行并通过调试来找到值缺失的原因。
可选类型可以让你判断值是否存在,你可以在代码中优雅地处理值缺失的情况。然而,在某些情况下,如果值缺失或者值并不满足特定的条件,你的代码可能没办法继续执行。这时,你可以在你的代码中触发一个*断言assertion*来结束代码运行并通过调试来找到值缺失的原因。
### 使用断言进行调试
@ -755,7 +756,7 @@ do {
如果你的代码在调试环境下触发了一个断言,比如你在 Xcode 中构建并运行一个应用,你可以清楚地看到不合法的状态发生在哪里并检查断言被触发时你的应用的状态。此外,断言允许你附加一条调试信息。
你可以使用全局`assert(_:_:)`函数来写一个断言。向`assert(_:_:)`函数传入一个结果为`true`或者`false`的表达式以及一条信息,当表达式的结果为`false`的时候这条信息会被显示:
你可以使用全局`assert(_:_file:line:)`函数来写一个断言。向这个函数传入一个结果为`true`或者`false`的表达式以及一条信息,当表达式的结果为`false`的时候这条信息会被显示:
```swift
let age = -3
@ -771,6 +772,9 @@ assert(age >= 0, "A person's age cannot be less than zero")
assert(age >= 0)
```
> 注意:
当代码使用优化编译的时候,断言将会被禁用,例如在 Xcode 中,使用默认的 target Release 配置选项来 build 时,断言会被禁用。
### 何时使用断言
当条件可能为假时使用断言但是最终一定要_保证_条件为真这样你的代码才能继续运行。断言的适用情景

View File

@ -312,7 +312,7 @@ if hasHeader {
- 表达式`a`必须是Optional类型
- 默认值`b`的类型必须要和`a`存储值的类型保持一致
空合运算符是对以下代码的简短表达方法
空合运算符是对以下代码的简短表达方法
```swift
a != nil ? a! : b
@ -323,7 +323,7 @@ a != nil ? a! : b
> 注意:
如果`a`为非空值(`non-nil`),那么值`b`将不会被估值。这也就是所谓的短路求值。
下文例子采用空合运算符,实现了在默认颜色名和可选自定义颜色名之间抉择:
下文例子采用空合运算符,实现了在默认颜色名和可选自定义颜色名之间抉择:
```swift
let defaultColorName = "red"

View File

@ -512,7 +512,7 @@ Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式
* UTF-16 代码单元集合 (利用字符串的`utf16`属性进行访问)
* 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式 (利用字符串的`unicodeScalars`属性进行访问)
下面由`D``o``g``‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和`🐶`(`DOG FACE`Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
下面由`D``o``g``‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和`<EFBFBD>`(`DOG FACE`Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
```swift
let dogString = "Dog‼🐶"
@ -526,16 +526,16 @@ let dogString = "Dog‼🐶"
其为`String.UTF8View`类型的属性,`UTF8View`是无符号8位 (`UInt8`) 值的集合,每一个`UInt8`值都是一个字符的 UTF-8 表示:
<table style='text-align:center'>
<tr height=77>
<tr height="77">
<td>Character</td>
<td>D<br>U+0044</td>
<td>o<br>U+006F</td>
<td>g<br>U+0067</td>
<td colspan=3><br>U+203C</td>
<td colspan=4>🐶<br>U+1F436</td>
<td colspan="3"><br>U+203C</td>
<td colspan="4">🐶<br>U+1F436</td>
</tr>
<tr height=77>
<td height=77>UTF-8<br>Code Unit</td>
<tr height="77">
<td height="77">UTF-8<br>Code Unit</td>
<td>68</td>
<td>111</td>
<td>103</td>
@ -548,7 +548,7 @@ let dogString = "Dog‼🐶"
<td>182</td>
</tr>
<tr>
<td height=77>Position</td>
<td height="77">Position</td>
<td>0</td>
<td>1</td>
<td>2</td>
@ -583,16 +583,16 @@ print("")
其为`String.UTF16View`类型的属性,`UTF16View`是无符号16位 (`UInt16`) 值的集合,每一个`UInt16`都是一个字符的 UTF-16 表示:
<table style='text-align:center'>
<tr height=77>
<tr height="77">
<td>Character</td>
<td>D<br>U+0044</td>
<td>o<br>U+006F</td>
<td>g<br>U+0067</td>
<td><br>U+203C</td>
<td colspan=2>🐶<br>U+1F436</td>
<td colspan="2">🐶<br>U+1F436</td>
</tr>
<tr height=77>
<td height=77>UTF-16<br>Code Unit</td>
<tr height="77">
<td height="77">UTF-16<br>Code Unit</td>
<td>68</td>
<td>111</td>
<td>103</td>
@ -601,7 +601,7 @@ print("")
<td>56374</td>
</tr>
<tr>
<td height=77>Position</td>
<td height="77">Position</td>
<td>0</td>
<td>1</td>
<td>2</td>
@ -638,7 +638,7 @@ print("")
<table style='text-align:center'>
<tr height=77>
<tr height="77">
<td>Character</td>
<td>D<br>U+0044</td>
<td>o<br>U+006F</td>
@ -646,8 +646,8 @@ print("")
<td><br>U+203C</td>
<td>🐶<br>U+1F436</td>
</tr>
<tr height=77>
<td height=77>UTF-16<br>Code Unit</td>
<tr height="77">
<td height="77">UTF-16<br>Code Unit</td>
<td>68</td>
<td>111</td>
<td>103</td>
@ -655,7 +655,7 @@ print("")
<td>128054</td>
</tr>
<tr>
<td height=77>Position</td>
<td height="77">Position</td>
<td>0</td>
<td>1</td>
<td>2</td>

View File

@ -14,6 +14,8 @@
- [While 循环](#while_loops)
- [条件语句](#conditional_statement)
- [控制转移语句Control Transfer Statements](#control_transfer_statements)
- [提前退出](#early_exit)
- [检测API是否可用](#checking_api_availability)
Swift提供了类似 C 语言的流程控制结构,包括可以多次执行任务的`for``while`循环,基于特定条件选择执行不同代码分支的`if``guard``switch`语句,还有控制流程跳转到其他代码的`break``continue`语句。
@ -713,7 +715,7 @@ print("Game over!")
同时请注意,当调用`continue gameLoop`去跳转到下一次循环迭代时,这里使用`gameLoop`标签并不是严格必须的。因为在这个游戏中,只有一个循环体,所以`continue`语句会影响到哪个循环体是没有歧义的。然而,`continue`语句使用`gameLoop`标签也是没有危害的。这样做符合标签的使用规则,同时参照旁边的`break gameLoop`,能够使游戏的逻辑更加清晰和易于理解。
<a name="early_exit"></a>
### 提前退出
## 提前退出
像`if`语句一样,`guard`的执行取决于一个表达式的布尔值。我们可以使用`guard`语句来要求条件必须为真时,以执行`guard`语句后的代码。不同于`if`语句,一个`guard`语句总是有一个`else`分句,如果条件不为真则执行`else`分局中的代码。
@ -746,7 +748,7 @@ greet(["name": "Jane", "location": "Cupertino"])
它可以使你的代码连贯的被执行而不需要将它包在`else`块中,它可以使你处理违反要求的代码接近要求。
<a name="checking_api_availability"></a>
### 检测API是否可用
## 检测API是否可用
Swift 有内置支持去检查接口的可用性的这可以确保我们不会不小心地使用对于当前部署目标不可用的API。

View File

@ -16,13 +16,13 @@
- [原始值Raw Values](#raw_values)
- [递归枚举Recursive Enumerations](#recursive_enumerations)
*枚举*定义了一个通用类型的一组相关值,使你可以在你的代码中以一种安全的方式来使用这些值。
**枚举**定义了一个通用类型的一组相关值,使你可以在你的代码中以一种安全的方式来使用这些值。
如果你熟悉 C 语言,你就会知道,在 C 语言中枚举将枚举名和一个整型值相对应。Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值。如果给枚举成员提供一个值(称为“原始”值),则该值的类型可以是字符串,字符,或是一个整型值或浮点数。
此外枚举成员可以指定任何类型的相关值存储到枚举成员值中就像其他语言中的联合体unions和变体variants。你可以定义一组通用的相关成员作为枚举的一部分每一组都有不同的一组与它相关的适当类型的数值。
在 Swift 中枚举类型是一等公民first-class。它们采用了很多传统上只被类class所支持的特征例如计算型属性computed properties用于提供关于枚举当前值的附加信息 实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。
在 Swift 中枚举类型是一等公民first-class。它们采用了很多传统上只被类class所支持的特征例如计算型属性computed properties用于提供关于枚举当前值的附加信息实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。
欲了解更多相关信息,请参见[属性Properties](./10_Properties.html)[方法Methods](./11_Methods.html)[构造过程Initialization](./14_Initialization.html)[扩展Extensions](./20_Extensions.html)和[协议Protocols](./21_Protocols.html)。
@ -33,11 +33,11 @@
```swift
enum SomeEnumeration {
// enumeration definition goes here
// 枚举定义放在这里
}
```
下是指南针四个方向的一个例子:
是指南针四个方向的例子:
```swift
enum CompassPoint {
@ -48,10 +48,10 @@ enum CompassPoint {
}
```
一个枚举中定义的值(`North``South``East``West`)是枚举的*成员值*(或*成员*)。`case`关键词表明新的一行成员值将被定义。
枚举中定义的值(如 `North``South``East``West`)是这个枚举的**成员值**(或**成员**)。`case`关键词表示一行新的成员值将被定义。
> 注意:
> 和 C 和 Objective-C 不同Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的`CompassPoints`例子中,`North``South``East`和`West`不会隐式地赋值为`0``1``2`和`3`。相反,这些不同的枚举成员在`CompassPoint`的一种显示定义中拥有各自不同的值。
> 和 C 和 Objective-C 不同Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的`CompassPoint`例子中,`North``South``East`和`West`不会隐式地赋值为`0``1``2`和`3`。相反,这些枚举成员本身就有完备的值,这些值是已经明确定义好的`CompassPoint`类型。
多个成员值可以出现在同一行上,用逗号隔开:
@ -119,19 +119,19 @@ default:
<a name="associated_values"></a>
## 相关值Associated Values
上一小节的例子演示了如何定义(分类)枚举的成员。你可以为`Planet.Earth`设置一个常量或者变量,并且在赋值之后查看这个值。不管怎样,如果有时候能够把其他类型的*相关值*和成员值一起存储起来会很有用。这能让你存储成员值之外的自定义信息,并且当你每次在代码中使用该成员时允许这个信息产生变化。
上一小节的例子演示了如何定义(分类)枚举的成员。你可以为`Planet.Earth`设置一个常量或者变量,并且在赋值之后查看这个值。不管怎样,如果有时候能够把其他类型的**相关值**和成员值一起存储起来会很有用。这能让你存储成员值之外的自定义信息,并且当你每次在代码中使用该成员时允许这个信息产生变化。
你可以定义 Swift 的枚举存储任何类型的相关值如果需要的话每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语言中的可辨识联合discriminated unions标签联合tagged unions或者变体variants相似。
例如,假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有 UPC-A 格式的一维t条形码,它使用数字 0 到 9。每一个条形码都有一个代表“数字系统”的数字该数字后接 5 个代表“生产代码”的数字接下来是5位“产品代码”。最后一个数字是“检查”位用来验证代码是否被正确扫描
例如,假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有 UPC-A 格式的一维条形码,它使用数字 0 到 9。每一个条形码都有一个代表“数字系统”的数字该数字后接 5 个代表“生产代码”的数字接下来是5位“产品代码”。最后一个数字是“检查”位用来验证代码是否被正确扫描
<img width="252" height="120" alt="" src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/barcode_UPC_2x.png">
其他商品上标有 QR 码格式的二维码,它可以使用任何 ISO8859-1 字符,并且可以编码一个最多拥有 2,953 字符的字符串:
其他商品上标有 QR 码格式的二维码,它可以使用任何 ISO 8859-1 字符,并且可以编码一个最多拥有 2953 字符的字符串:
<img width="169" height="169" alt="" src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/barcode_QR_2x.png">
对于库存跟踪系统来说,能够把 UPC-A 码作为个整型值的元组,和把 QR 码作为一个任何长度的字符串存储起来是方便的。
对于库存跟踪系统来说,能够把 UPC-A 码作为个整型值的元组,和把 QR 码作为一个任何长度的字符串存储起来是方便的。
在 Swift 中,使用如下方式定义两种商品条码的枚举:
@ -229,7 +229,7 @@ enum Planet: Int {
当使用字符串作为枚举类型的初值时,每个枚举成员的隐式初值则为该成员的名称。
下面的例子是`CompassPoint`枚举类型的精简版,使用字符串作为初值类型,隐式初始化为个方向的名称:
下面的例子是`CompassPoint`枚举类型的精简版,使用字符串作为初值类型,隐式初始化为个方向的名称:
```swift
enum CompassPoint: String {
@ -248,11 +248,10 @@ let earthsOrder = Planet.Earth.rawValue
let sunsetDirection = CompassPoint.West.rawValue
// sunsetDirection 值为 "West"
```
### 使用原始值来初始化(Initializing from a Raw Value)
### 使用原始值初始化枚举变量Initializing from a Raw Value
如果在定义枚举类型的时候使用了原始值,那么将会自动获得一个初始化方法,这个方法将原始值类型作为参数,返回枚举成员或`nil`。你可以使用这种初始化方法来创建一个新的枚举变量。
如果在定义枚举类型的时候使用了原始值,那么将会自动获得一个初始化方法,这个方法将原始值类型作为参数,返回值是枚举成员或`nil`。你可以使用这种初始化方法来创建一个新的枚举变量。
这个例子通过原始值`7`从而创建枚举成员:
@ -261,7 +260,7 @@ let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet 类型为 Planet? 值为 Planet.Uranus
```
然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet``Planet?`类型,或“可选的`Planet`”。
然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个**可选**的枚举成员。在上面的例子中,`possiblePlanet``Planet?`类型,或“可选的`Planet`”。
>注意:
>原始值构造器是一个可失败构造器,因为并不是每一个原始值都有与之对应的枚举成员。更多信息请参见[可失败构造器](../chapter3/05_Declarations#failable_initializers)
@ -288,9 +287,9 @@ if let somePlanet = Planet(rawValue: positionToFind) {
<a name="recursive_enumerations"></a>
## 递归枚举Recursive Enumerations
在对操作符进行描述的时候,使用枚举类型来对数据建模很方便,因为需要考虑的情况固定可枚举。操作符可以将两个由数字组成的算数表达式连接起来,例如,将`5`连接成复杂一些的表达式`5+4`.
在对操作符进行描述的时候,使用枚举类型来对数据建模很方便,因为需要考虑的情况固定可枚举。操作符可以将两个由数字组成的算数表达式连接起来,例如,将`5`连接成复杂一些的表达式`5+4`
表达式的一个重要特性是,表达式可以嵌套使用。例如,表达式`(5 + 4) * 2`乘号右边是一个数字,左边则是另一个表达式。因为数据是嵌套的,因而用来存储数据的枚举类型也许要支持这种嵌套————这表示枚举类型需要支持递归。
表达式的一个重要特性是,表达式可以嵌套使用。例如,表达式`(5 + 4) * 2`乘号右边是一个数字,左边则是另一个表达式。因为数据是嵌套的,因而用来存储数据的枚举类型也许要支持这种嵌套————这表示枚举类型需要支持递归。
`递归枚举recursive enumeration`是一种枚举类型,表示它的枚举中,有一个或多个枚举成员拥有该枚举的其他成员作为相关值。使用递归枚举时,编译器会插入一个中间层。你可以在枚举成员前加上`indirect`来表示这成员可递归。
@ -317,7 +316,7 @@ indirect enum ArithmeticExpression {
上面定义的枚举类型可以存储三种算数表达式:纯数字、两个表达式的相加、两个表达式相乘。`Addition``Multiplication`成员的相关值也是算数表达式————这些相关值使得嵌套表达式成为可能。
递归函数可以很直观地使用具有递归性质的数据结构。例如,下面是一个计算算表达式的函数:
递归函数可以很直观地使用具有递归性质的数据结构。例如,下面是一个计算算表达式的函数:
```swift
func evaluate(expression: ArithmeticExpression) -> Int {
@ -340,4 +339,4 @@ print(evaluate(product))
// 输出 "18"
```
该函数如果遇到纯数字,就直接返回该数字的值。如果遇到的是加法或乘法算,则分别计算左边表达式和右边表达式的值,然后相加或相乘。
该函数如果遇到纯数字,就直接返回该数字的值。如果遇到的是加法或乘法算,则分别计算左边表达式和右边表达式的值,然后相加或相乘。

View File

@ -305,6 +305,7 @@ stepCounter.totalSteps = 896
> 注意:
> 跟实例的存储属性不同,必须给存储型类型属性指定默认值,因为类型本身无法在初始化过程中使用构造器给类型属性赋值。
> 存储型类型属性是延迟初始化的(lazily initialized),它们只有在第一次被访问的时候才会被初始化。即使它们被多个线程同时访问,系统也保证只会对其进行初始化一次,并且不需要对其使用 `lazy` 修饰符。
<a name="type_property_syntax"></a>
###类型属性语法

View File

@ -20,21 +20,21 @@
- [通过闭包和函数来设置属性的默认值](#setting_a_default_property_value_with_a_closure_or_function)
构造过程是为了使用某个类、结构体或枚举类型的实例而进行的准备过程。这个过程包含了为实例中每个存储型属性设置初始值和为其执行必要的准备和初始化任务
构造过程是使用类、结构体或枚举类型一个实例的准备过程。在新实例可用前必须执行这个过程,具体操作包括设置实例中每个存储型属性初始值和执行其他必须的设置或初始化工作
构造过程是通过定义构造器(`Initializers`)来实现,这些构造器可以看做是用来创建特定类型实例的特殊方法。与 Objective-C 中的构造器不同Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
通过定义构造器(`Initializers`)来实现构造过程,这些构造器可以看做是用来创建特定类型实例的特殊方法。与 Objective-C 中的构造器不同Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
类的实例也可以通过定义析构器(`deinitializer`)在实例释放之前执行特定的清除工作。想了解更多关于析构器的内容,请参考[析构过程](./15_Deinitialization.html)。
<a name="setting_initial_values_for_stored_properties"></a>
## 存储型属性的初始
## 设置存储型属性的初始值
类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值。存储型属性的值不能处于一个未知的状态。
类和结构体在创建实例时,必须为所有存储型属性设置合适的初始值。存储型属性的值不能处于一个未知的状态。
你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。以下节将详细介绍这两种方法。
你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。以下节将详细介绍这两种方法。
>注意:
当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观测器`property observers`)。
当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观察者`property observers`)。
### 构造器
@ -67,7 +67,7 @@ print("The default temperature is \(f.temperature)° Fahrenheit")
如前所述,你可以在构造器中为存储型属性设置初始值。同样,你也可以在属性声明时为其设置默认值。
>注意:
如果一个属性总是使用同一个初始值,可以为其设置一个默认值。无论定义默认值还是在构造器中赋值,最终它们实现的效果是一样的,只不过默认值属性的初始化和属性的声明结合的更紧密。使用默认值能让你的构造器更简洁、更清晰,且能通过默认值自动推导出属性的类型;同时,它也能让你充分利用默认构造器、构造器继承(后续章节将讲到)等特性
如果一个属性总是使用相同的初始值,那么为其设置一个默认值比每次都在构造器中赋值要好。两种方法的效果是一样的,只不过使用默认值属性的初始化和声明结合的更紧密。使用默认值能让你的构造器更简洁、更清晰,且能通过默认值自动推导出属性的类型;同时,它也能让你充分利用默认构造器、构造器继承等特性(后续章节将讲到)。
你可以使用更简单的方式在定义结构体`Fahrenheit`时为属性`temperature`设置默认值:
@ -80,17 +80,17 @@ struct Fahrenheit {
<a name="customizing_initialization"></a>
## 自定义构造过程
你可以通过输入参数和可选属性类型来定义构造过程,也可以在构造过程中修改常量属性。这些都将在后面章节中提到。
你可以通过输入参数和可选属性类型来定义构造过程,也可以在构造过程中修改常量属性。这些都将在后面章节中提到。
### 构造参数
你可以在定义构造器时提供构造参数,为其提供自定义构造所需值的类型和名字。构造参数的功能和语法跟函数和方法参数相同。
自定义`构造过程`时,可以在定义中提供构造参数,指定所需值的类型和名字。构造参数的功能和语法跟函数和方法参数相同。
下面例子中定义了一个包含摄氏度温度的结构体`Celsius`。它定义了两个不同的构造器:`init(fromFahrenheit:)``init(fromKelvin:)`,二者分别通过接受不同刻度表示的温度值来创建新的实例:
```swift
struct Celsius {
var temperatureInCelsius: Double = 0.0
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
@ -199,12 +199,12 @@ cheeseQuestion.response = "Yes, I do like cheese."
<a name="assigning_constant_properties_during_initialization"></a>
### 构造过程中常量属性的修改
只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。
你可以在构造过程中的任意时间点修改常量属性的值,只要在构造过程结束时是一个确定的值。一旦常量属性被赋值,它将永远不可更改
>注意:
某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
于类的实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
你可以修改上面的`SurveyQuestion`示例,用常量属性替代变量属性`text`指明问题内容`text`创建之后不会再被修改。尽管`text`属性现在是常量,我们仍然可以在其类的构造器中设置它的值:
你可以修改上面的`SurveyQuestion`示例,用常量属性替代变量属性`text`表示问题内容`text``SurveyQuestion`的实例被创建之后不会再被修改。尽管`text`属性现在是常量,我们仍然可以在其类的构造器中设置它的值:
```swift
class SurveyQuestion {
@ -226,7 +226,7 @@ beetsQuestion.response = "I also like beets. (But not with cheese.)"
<a name="default_initializers"></a>
## 默认构造器
Swift 将为所有属性已提供默认值的且自身没有定义任何构造器的结构体或基类,提供一个默认构造器。这个默认构造器将简单的创建一个所有属性值都设置为默认值的实例。
如果结构体和类的所有属性都有默认值,同时没有定义构造器,那么 Swift 会给这些结构体和类创建一个默认构造器。这个默认构造器将简单的创建一个所有属性值都设置为默认值的实例。
下面例子中创建了一个类`ShoppingListItem`,它封装了购物清单中的某一项的属性:名字(`name`)、数量(`quantity`)和购买状态 `purchase state`
@ -635,7 +635,7 @@ let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)
class ShoppingListItem: RecipeIngredient {
var purchased = false
var description: String {
var output = "\(quantity) x \(name.lowercaseString)"
var output = "\(quantity) x \(name)"
output += purchased ? " ✔" : " ✘"
return output
}
@ -674,7 +674,7 @@ for item in breakfastList {
<a name="failable_initializers"></a>
## 可失败构造器
如果一个类结构体或枚举类型的对象,在构造自身的过程中有可能失败,则为其定义一个可失败构造器,是非常有必要的。这里所指的“失败”是指,如给构造器传入无效的参数值,或缺少某种所需的外部资源,又或是不满足某种必要的条件等。
如果一个类结构体或枚举类型的对象,在构造自身的过程中有可能失败,则为其定义一个可失败构造器,是非常有的。这里所指的“失败”是指,如给构造器传入无效的参数值,或缺少某种所需的外部资源,又或是不满足某种必要的条件等。
为了妥善处理这种构造过程中可能会失败的情况。你可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在`init`关键字后面加添问号`(init?)`
@ -723,11 +723,11 @@ if anonymousCreature == nil {
```
> 注意:
空字符串(`""`)和一个值为`nil`的可选类型的字符串是两个完全不同的概念。上例中的空字符串(`""`)其实是一个有效的,非可选类型的字符串。这里我们只所以让`Animal`的可失败构造器,构建对象失败,只是因为对于`Animal`这个类的`species`属性来说,它更适合有一个具体的值,而不是空字符串。
空字符串(`""`,而不是`"Giraffe"`)和一个值为`nil`的可选类型的字符串是两个完全不同的概念。上例中的空字符串(`""`)其实是一个有效的,非可选类型的字符串。这里我们只所以让`Animal`的可失败构造器,构建对象失败,只是因为对于`Animal`这个类的`species`属性来说,它更适合有一个具体的值,而不是空字符串。
###枚举类型的可失败构造器
你可以通过构造一个带一个或多个参数的可失败构造器来获取枚举类型中特定的枚举成员。还能在参数不满足你所期望的条件时,导致构造失败。
你可以通过构造一个带一个或多个参数的可失败构造器来获取枚举类型中特定的枚举成员。还能在参数不满足枚举成员期望的条件时,构造失败。
下例中定义了一个名为TemperatureUnit的枚举类型。其中包含了三个可能的枚举成员(`Kelvin``Celsius`,和 `Fahrenheit`)和一个被用来找到`Character`值所对应的枚举成员的可失败构造器:
@ -791,9 +791,11 @@ if unknownUnit == nil {
###类的可失败构造器
值类型(如结构体或枚举类型)的可失败构造器,对何时何地触发构造失败这个行为没有任何的限制。比如在前面的例子中,结构体`Animal`的可失败构造器触发失败的行为,甚至发生在`species`属性的值被初始化以前。而对类而言,就没有那么幸运了。类的可失败构造器只能在所有的类属性被初始化后和所有类之间的构造器之间的代理调用发生完后触发失败行为。
值类型(如结构体或枚举类型)的可失败构造器,对何时何地触发构造失败这个行为没有任何的限制。比如在前面的例子中,结构体`Animal`的可失败构造器触发失败的行为,甚至发生在`species`属性的值被初始化以前。
下例子中,定义了一个名为`Product`的类,其内部结构和结构体`Animal`很相似,内部也有一个名为`name``String`类型的属性。由于该属性的值同样不能为空字符串,所以我们加入了可失败构造器来确保该类满足上述条件。但由于`Product`类不是一个结构体,所以当想要在该类中添加可失败构造器触发失败条件时,必须确保`name`属性被初始化。因此我们把`name`属性的`String`类型做了一点点小小的修改,把其改为隐式解析可选类型(`String!`),来确保可失败构造器触发失败条件时,所有类属性都被初始化了。因为所有可选类型都有一个默认的初始值`nil`。因此最后`Product`类可写为:
而对类而言,就没有那么幸运了。类的可失败构造器只能在所有的类属性被初始化后和所有类之间的构造器之间的代理调用发生完后触发失败行为。
下面例子展示了如何使用隐式解析可选类型来实现这个类的可失败构造器的要求:
```swift
class Product {
@ -804,8 +806,13 @@ class Product {
}
}
```
上面定义的`Product`类,其内部结构和之前`Animal`结构体很相似。`Product`类有一个不能为空字符串的`name`常量属性。为了强制满足这个要求,`Product`类使用了可失败构造器来确保这个属性的值在构造器成功时不为空。
因为`name`属性是一个常量,所以一旦`Product`类构造成功,`name`属性肯定有一个非`nil`的值。因此完全可以放心大胆的直接访问`Product`类的`name`属性,而不用考虑去检查`name`属性是否有值。
毕竟,`Product`是一个类而不是结构体,也就不能和`Animal`一样了。`Product`类的所有可失败构造器必须在自己失败前给`name`属性一个初始值。
上面的例子中,`Product`类的`name`属性被定义为隐式解析可选字符串类型(`String!`)。因为它是一个可选类型,所以在构造过程里的赋值前,`name`属性有个默认值`nil`。用默认值`nil`意味着`Product`类的所有属性都有一个合法的初始值。因而,在构造器中给`name`属性赋一个特定的值前,可失败构造器能够在传入一个空字符串时触发构造过程的失败。
因为`name`属性是一个常量,所以一旦`Product`类构造成功,`name`属性肯定有一个非`nil`的值。即使它被定义为隐式解析可选类型,也完全可以放心大胆地直接访问,而不用考虑`name`属性是否有值。
```swift
if let bowTie = Product(name: "bow tie") {
@ -830,9 +837,10 @@ if let bowTie = Product(name: "bow tie") {
class CartItem: Product {
let quantity: Int!
init?(name: String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
if quantity < 1 { return nil }
self.quantity = quantity
}
}
```
@ -897,7 +905,7 @@ class Document {
}
```
下面这个例子,定义了一个名为`AutomaticallyNamedDocument``Document`类的子类。这个子类重写了类的两个指定构造器确保不论在何种情况下`name`属性总是有一个非空字符串`[Untitled]`的值
下面这个例子,定义了一个`Document`类的子类`AutomaticallyNamedDocument`。这个子类重写了类的两个指定构造器确保不论是通过没有 name 参数的构造器,还是通过传一个空字符串给`init(name:)`构造器,生成的实例中的`name`属性总有初始值`"[Untitled]"`
```swift
class AutomaticallyNamedDocument: Document {
@ -916,15 +924,26 @@ class AutomaticallyNamedDocument: Document {
}
```
`AutomaticallyNamedDocument`用一个非可失败构造器`init(name:)`,重写了类的可失败构造器`init?(name:)`。因为子类用不同的方法处理了`name`属性的值为一个空字符串的这种情况。所以子类将不再需要一个可失败的构造器。
`AutomaticallyNamedDocument`用一个非可失败构造器`init(name:)`,重写了类的可失败构造器`init?(name:)`。因为子类用不同的方法处理了`name`属性的值为一个空字符串的这种情况。所以子类将不再需要一个可失败的构造器,用一个非可失败版本代替了父类的版本
你可以在构造器中调用父类的可失败构造器强制解包,以实现子类的非可失败构造器。比如,下面的`UntitledDocument `子类总有值为`"[Untitled]"`的 name 属性,它在构造过程中用了父类的可失败的构造器`init(name:)`
```swift
class UntitledDocument: Document {
override init() {
super.init(name: "[Untitled]")!
}
}
```
在这个例子中,如果在调用父类的构造器`init(name:)`时传给 name 的是空字符串,那么强制解绑操作会造成运行时错误。不过,因为这里是通过字符串常量来调用它,所以并不会发生运行时错误。
###可失败构造器 init!
通常来说我们通过在`init`关键字后添加问号的方式来定义一个可失败构造器,但你也可以使用通过在`init`后面添加惊叹号的方式来定义一个可失败构造器`(init!)`,该可失败构造器将会构建一个特定类型的隐式解析可选类型的对象。
通常来说我们通过在`init`关键字后添加问号的方式`init?`来定义一个可失败构造器,但你也可以使用通过在`init`后面添加惊叹号的方式来定义一个可失败构造器`(init!)`,该可失败构造器将会构建一个特定类型的隐式解析可选类型的对象。
你可以在 `init? `构造器中代理调用 `init!`构造器,反之亦然。
你也可以用 `init?`重写 `init!`,反之亦然。
你还可以用 `init`代理调用`init!`,但这会触发一个断言:是否 `init!` 构造器会触发构造失败?
你还可以用 `init`代理调用`init!`,但这会触发一个断言: `init!` 构造器是否会触发构造失败?
<a name="required_initializers"></a>
##必要构造器
@ -938,7 +957,7 @@ class SomeClass {
}
}
```
子类重写类的必要构造器时,必须在子类的构造器前同样添加`required`修饰符以确保当其它类继承该子类时,该构造器同为必要构造器。在重写类的必要构造器时,不需要添加`override`修饰符:
子类重写类的必要构造器时,必须在子类的构造器前添加`required`修饰符,这是为了保证继承链上子类的构造器也是必要构造器。在重写类的必要构造器时,不需要添加`override`修饰符:
```swift
class SomeSubclass: SomeClass {

View File

@ -17,7 +17,7 @@
- [闭包引起的循环强引用](#strong_reference_cycles_for_closures)
- [解决闭包引起的循环强引用](#resolving_strong_reference_cycles_for_closures)
Swift 使用自动引用计数ARC机制来跟踪和管理你的应用程序的内存。通常情况下Swift 内存管理机制会一直起作用你无须自己来考虑内存的管理。ARC 会在类的实例不再被使用时,自动释放其占用的内存。
Swift 使用自动引用计数ARC机制来跟踪和管理你的应用程序的内存。通常情况下Swift 内存管理机制会一直起作用你无须自己来考虑内存的管理。ARC 会在类的实例不再被使用时,自动释放其占用的内存。
然而在少数情况下ARC 为了能帮助你管理内存,需要更多的关于你的代码之间关系的信息。本章描述了这些情况,并且为你示范怎样启用 ARC 来管理你的应用程序的内存。
@ -261,6 +261,13 @@ unit4A = nil
上面的两段代码展示了变量`john``unit4A`在被赋值为`nil`后,`Person`实例和`Apartment`实例的析构函数都打印出“销毁”的信息。这证明了引用循环被打破了。
<!--
NOTE
In systems that use garbage collection, weak pointers are sometimes used to implement a simple caching mechanism because objects with no strong references are deallocated only when memory pressure triggers garbage collection. However, with ARC, values are deallocated as soon as their last strong reference is removed, making weak references unsuitable for such a purpose.
-->
>注意:
在使用垃圾收集的系统里,弱指针有时用来实现简单的缓冲机制,因为没有强引用的对象只会在内存压力触发垃圾收集时才被销毁。但是在 ARC 中,一旦值的最后一个强引用被删除,就会被立即销毁,这导致弱引用并不适合上面的用途。
<a name="2"></a>
### 无主引用
@ -442,6 +449,20 @@ class HTMLElement {
可以像实例方法那样去命名、使用`asHTML`属性。然而,由于`asHTML`是闭包而不是实例方法,如果你想改变特定元素的 HTML 处理的话,可以用自定义的闭包来取代默认值。
<!--
For example, the asHTML property could be set to a closure that defaults to some text if the text property is nil, in order to prevent the representation from returning an empty HTML tag:
-->
例如,可以将一个闭包赋值给`asHTML`属性,这个闭包能在文本属性是 nil 时用默认文本,这是为了避免返回一个空的 `HTML` 标签:
```swift
let heading = HTMLElement(name: "h1")
let defaultText = "some default text"
heading.asHTML = {
return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
}
print(heading.asHTML())
// prints "<h1>some default text</h1>"
```
> 注意:
`asHTML`声明为`lazy`属性因为只有当元素确实需要处理为HTML输出的字符串时才需要使用`asHTML`。也就是说,在默认的闭包中可以使用`self`,因为只有当初始化完成以及`self`确实存在后,才能访问`lazy`属性。
@ -480,8 +501,8 @@ paragraph = nil
在定义闭包时同时定义捕获列表作为闭包的一部分,通过这种方式可以解决闭包和类实例之间的循环强引用。捕获列表定义了闭包体内捕获一个或者多个引用类型的规则。跟解决两个类实例间的循环强引用一样,声明每个捕获的引用为弱引用或无主引用,而不是强引用。应当根据代码关系来决定使用弱引用还是无主引用。
>注意:
Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod`(而不只是`someProperty``someMethod`)。这提醒你可能会一不小心就捕获了`self`
>注意
Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod()`(而不只是`someProperty``someMethod()`)。这提醒你可能会一不小心就捕获了`self`
###定义捕获列表

View File

@ -6,7 +6,9 @@
> 校对:[dabing1022](https://github.com/dabing1022)
> 2.0
> 翻译+校对[futantan](https://github.com/futantan)
> 翻译:[futantan](https://github.com/futantan)
> 校对:[小铁匠Linus](https://github.com/kevin833752)
> 定稿:[shanksyang](http://codebuild.me)
本页包含内容:
@ -19,7 +21,7 @@
- [委托(代理)模式Delegation](#delegation)
- [在扩展中添加协议成员Adding Protocol Conformance with an Extension](#adding_protocol_conformance_with_an_extension)
- [通过扩展补充协议声明Declaring Protocol Adoption with an Extension](#declaring_protocol_adoption_with_an_extension)
- [集合中的协议类型Collections of Protocol Types](#collections_of_protocol_types)
- [协议类型的集合Collections of Protocol Types](#collections_of_protocol_types)
- [协议的继承Protocol Inheritance](#protocol_inheritance)
- [类专属协议Class-Only Protocol](#class_only_protocol)
- [协议合成Protocol Composition](#protocol_composition)
@ -30,6 +32,7 @@
`协议`定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性。类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。任意能够满足协议要求的类型被称为`遵循(conform)`这个协议。
除了遵循协议的类型必须实现那些指定的规定以外,还可以对协议进行扩展,实现一些特殊的规定或者一些附加的功能,使得遵循的类型能够收益。
<a name="protocol_syntax"></a>
## 协议的语法
@ -60,11 +63,11 @@ class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
<a name="property_requirements"></a>
## 对属性的规定
协议可以规定其`遵循者`提供特定名称和类型的`实例属性(instance property)``类属性(type property)`,而不指定是`存储型属性(stored property)`还是`计算型属性(calculate property)`。此外还必须指明是只读的还是可读可写的。
协议可以规定其`遵循者`提供特定名称和类型的`实例属性(instance property)``类属性(type property)`,而不指定是`存储型属性(stored property)`还是`计算型属性(calculate property)`。此外还必须指明是只读的还是可读可写的。
如果协议规定属性是可读可写的,那么这个属性不能是常量或只读的计算属性。如果协议只要求属性是只读的(gettable),那个属性不仅可以是只读的,如果你代码需要的话,也可以是可写的。
协议中的通常用var来声明属性在类型声明后加上`{ set get }`来表示属性是可读可写的,只读属性则用`{ get }`来表示。
协议中的通常用var来声明变量属性,在类型声明后加上`{ set get }`来表示属性是可读可写的,只读属性则用`{ get }`来表示。
```swift
protocol SomeProtocol {
@ -73,7 +76,7 @@ protocol SomeProtocol {
}
```
在协议中定义类属性(type property)时,总是使用`static`关键字作为前缀。当协议的遵循者是类时,可以使用`class``static`关键字来声明类属性,但是在协议的定义中,仍然要使用`static`关键字。
在协议中定义类属性(type property)时,总是使用`static`关键字作为前缀。当协议的遵循者是类时,可以使用`class``static`关键字来声明类属性
```swift
protocol AnotherProtocol {
@ -81,7 +84,7 @@ protocol AnotherProtocol {
}
```
如下所示,这是一个含有一个实例属性要求的协议
如下所示,这是一个含有一个实例属性要求的协议
```swift
protocol FullyNamed {
@ -89,9 +92,9 @@ protocol FullyNamed {
}
```
`FullyNamed`协议除了要求协议的遵循者提供fullName属性外,对协议对遵循者的类型并没有特别的要求。这个协议表示,任何遵循`FullyNamed`协议的类型,都具有一个可读的`String`类型实例属性`fullName`
`FullyNamed`协议除了要求协议的遵循者提供全名属性外,对协议对遵循者的类型并没有特别的要求。这个协议表示,任何遵循`FullyNamed`协议的类型,都具有一个可读的`String`类型实例属性`fullName`
下面是一个遵循`FullyNamed`协议的简单结构体
下面是一个遵循`FullyNamed`协议的简单结构体
```swift
struct Person: FullyNamed{
@ -103,7 +106,7 @@ let john = Person(fullName: "John Appleseed")
这个例子中定义了一个叫做`Person`的结构体,用来表示具有名字的人。从第一行代码中可以看出,它遵循了`FullyNamed`协议。
`Person`结构体的每一个实例都有一个叫做`fullName``String`类型的存储型属性。这正好满足了`FullyNamed`协议的要求,也就意味着,`Person`结构体完整的`遵循`了协议。(如果协议要求未被完全满足,在编译时会报错)
`Person`结构体的每一个实例都有一个`String`类型的存储型属性`fullName`。这正好满足了`FullyNamed`协议的要求,也就意味着,`Person`结构体完整的`遵循`了协议。(如果协议要求未被完全满足,在编译时会报错)
下面是一个更为复杂的类,它采用并遵循了`FullyNamed`协议:
@ -120,17 +123,17 @@ class Starship: FullyNamed {
}
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName is "USS Enterprise"
// ncc1701.fullName "USS Enterprise"
```
Starship类把`fullName`属性实现为只读的计算型属性。每一个`Starship`类的实例都有一个名为`name`的属性和一个名为`prefix`的可选属性。 当`prefix`存在时,将`prefix`插入到`name`之前来为Starship构建`fullName``prefix`不存在时,则将直接用`name`构建`fullName`
`Starship`类把`fullName`属性实现为只读的计算型属性。每一个`Starship`类的实例都有一个名为`name`的属性和一个名为`prefix`的可选属性。 当`prefix`存在时,将`prefix`插入到`name`之前来为Starship构建`fullName``prefix`不存在时,则将直接用`name`构建`fullName`
<a name="method_requirements"></a>
## 对方法的规定
协议可以要求其遵循者实现某些指定的实例方法或类方法。这些方法作为协议的一部分,像普通的方法一样放在协议的定义中,但是不需要大括号和方法体。可以在协议中定义具有可变参数的方法,和普通方法的定义方式相同。但是在协议的方法定义中,不支持参数默认值。
正如对属性的规定中所说的,在协议中定义类方法的时候,总是使用`static`关键字作为前缀。当协议的遵循者是类的时候,虽然你可以在类的实现中使用`class`或者`static`来实现类方法,但是在协议中声明类方法,仍然要使用`static`关键字。
正如对属性的规定中所说的,在协议中定义类方法的时候,总是使用`static`关键字作为前缀。当协议的遵循者是类的时候,你可以在类的实现中使用`class`或者`static`来实现类方法
```swift
protocol SomeProtocol {
@ -138,7 +141,7 @@ protocol SomeProtocol {
}
```
下面的例子定义了含有一个实例方法的协议
下面的例子定义了含有一个实例方法的协议
```swift
protocol RandomNumberGenerator {
@ -184,7 +187,7 @@ print("And another one: \(generator.random())")
如下所示,`Togglable`协议含有名为`toggle`的实例方法。根据名称推测,`toggle()`方法将通过改变实例属性,来切换遵循该协议的实例的状态。
`toggle()`方法在定义的时候,使用`mutating`关键字标记,这表明当它被调用时该方法将会改变协议遵循者实例的状态
`toggle()`方法在定义的时候,使用`mutating`关键字标记,这表明当它被调用时该方法将会改变协议遵循者实例的状态
```swift
protocol Togglable {
@ -194,7 +197,7 @@ protocol Togglable {
当使用`枚举``结构体`来实现`Togglable`协议时,需要提供一个带有`mutating`前缀的`toggle`方法。
下面定义了一个名为`OnOffSwitch`的枚举类型。这个枚举类型在两种状态之间进行切换,用枚举成员`On``Off`表示。枚举类型的`toggle`方法被标记为`mutating`以满足`Togglable`协议的要求
下面定义了一个名为`OnOffSwitch`的枚举类型。这个枚举类型在两种状态之间进行切换,用枚举成员`On``Off`表示。枚举类型的`toggle`方法被标记为`mutating`以满足`Togglable`协议的要求
```swift
enum OnOffSwitch: Togglable {
@ -243,7 +246,7 @@ class SomeClass: SomeProtocol {
>注意
>如果类已经被标记为`final`,那么不需要在协议构造器的实现中使用`required`修饰符。因为final类不能有子类。关于`final`修饰符的更多内容,请参见[防止重写](./13_Inheritance.html#preventing_overrides)。
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示`required``override`修饰符
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示`required``override`修饰符
```swift
protocol SomeProtocol {
@ -287,7 +290,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
> 注意
> 协议是一种类型,因此协议类型的名称应与其他类型(IntDoubleString)的写法相同,使用大写字母开头的驼峰式写法,例如(`FullyNamed`和`RandomNumberGenerator`)
如下所示,这个示例中将协议当做类型来使用
如下所示,这个示例中将协议当做类型来使用
```swift
class Dice {
@ -329,9 +332,9 @@ for _ in 1...5 {
<a name="delegation"></a>
## 委托(代理)模式
委托是一种设计模式,它允许`类`或`结构体`将一些需要它们负责的功能`交由(委托)`给其他的类型的实例。委托模式的实现很简单: 定义协议来封装那些需要被委托的函数和方法, 使其`遵循者`拥有这些被委托的`函数和方法`。委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的类型信息。
委托是一种设计模式,它允许`类`或`结构体`将一些需要它们负责的功能`交由(委托)`给其他的类型的实例。委托模式的实现很简单: 定义协议来封装那些需要被委托的函数和方法,使其`遵循者`拥有这些被委托的`函数和方法`。委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的类型信息。
下面的例子是两个基于骰子游戏的协议:
下面的例子是两个基于骰子游戏的协议
```swift
protocol DiceGame {
@ -346,7 +349,7 @@ protocol DiceGameDelegate {
}
```
`DiceGame`协议可以在任意含有骰子的游戏中实现。`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程
`DiceGame`协议可以在任意含有骰子的游戏中实现。`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程
如下所示,`SnakesAndLadders`是`Snakes and Ladders`([Control Flow](./05_Control_Flow.html)章节有该游戏的详细介绍)游戏的新版本。新版本使用`Dice`作为骰子,并且实现了`DiceGame``DiceGameDelegate`协议,后者用来记录游戏的过程:
@ -393,7 +396,7 @@ class SnakesAndLadders: DiceGame {
因为`delegate`是一个遵循`DiceGameDelegate`的可选属性,因此在`play()`方法中使用了`可选链`来调用委托方法。 若`delegate`属性为`nil` 则delegate所调用的方法失效并不会产生错误。若`delegate`不为`nil`,则方法能够被调用
如下所示,`DiceGameTracker`遵循了`DiceGameDelegate`协议
如下所示,`DiceGameTracker`遵循了`DiceGameDelegate`协议
```swift
class DiceGameTracker: DiceGameDelegate {
@ -421,20 +424,20 @@ class DiceGameTracker: DiceGameDelegate {
无论当前进行的是何种游戏,`game`都遵循`DiceGame`协议以确保`game`含有`dice`属性,因此在`gameDidStart(_:)`方法中可以通过传入的`game`参数来访问`dice`属性,进而打印出`dice``sides`属性的值。
`DiceGameTracker`的运行情况,如下所示:
`DiceGameTracker`的运行情况,如下所示
```swift
let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6-sided dice
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4 turns
// 开始一个新的Snakes and Ladders的游戏
// 游戏使用 6 面的骰子
// 翻转得到 3
// 翻转得到 5
// 翻转得到 4
// 翻转得到 5
// 游戏进行了 4 轮
```
<a name="adding_protocol_conformance_with_an_extension"></a>
@ -445,19 +448,19 @@ game.play()
> 注意
> 通过扩展为已存在的类型遵循协议时,该类型的所有实例也会随之添加协议中的方法
例如`TextRepresentable`协议,任何想要表示一些文本内容的类型都可以遵循该协议。这些想要表示的内容可以是类型本身的描述,也可以是当前内容的版本:
例如`TextRepresentable`协议,任何想要表示一些文本内容的类型都可以遵循该协议。这些想要表示的内容可以是类型本身的描述,也可以是当前内容的版本
```swift
protocol TextRepresentable {
func asText() -> String
var textualDescription: String { get }
}
```
可以通过扩展,为上一节中提到的`Dice`增加类遵循`TextRepresentable`协议的功能
可以通过扩展,为上一节中提到的`Dice`增加类遵循`TextRepresentable`协议的功能
```swift
extension Dice: TextRepresentable {
func asText() -> String {
var textualDescription: String {
return "A \(sides)-sided dice"
}
}
@ -468,7 +471,7 @@ extension Dice: TextRepresentable {
```swift
let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator())
print(d12.asText())
print(d12. textualDescription)
// 输出 "A 12-sided dice"
```
@ -476,11 +479,11 @@ print(d12.asText())
```swift
extension SnakesAndLadders: TextRepresentable {
func asText() -> String {
var textualDescription: String {
return "A game of Snakes and Ladders with \(finalSquare) squares"
}
}
print(game.asText())
print(game.textualDescription)
// 输出 "A game of Snakes and Ladders with 25 squares"
```
@ -492,29 +495,29 @@ print(game.asText())
```swift
struct Hamster {
var name: String
func asText() -> String {
var textualDescription: String {
return "A hamster named \(name)"
}
}
extension Hamster: TextRepresentable {}
```
从现在起,`Hamster`的实例可以作为`TextRepresentable`类型使用
从现在起,`Hamster`的实例可以作为`TextRepresentable`类型使用
```swift
let simonTheHamster = Hamster(name: "Simon")
let somethingTextRepresentable: TextRepresentable = simonTheHamster
print(somethingTextRepresentable.asText())
print(somethingTextRepresentable.textualDescription)
// 输出 "A hamster named Simon"
```
> 注意
> 即使满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出显式的协议声明
> 即使满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出显式的协议声明
<a name="collections_of_protocol_types"></a>
## 集合中的协议类型
## 协议类型的集合
协议类型可以在集合使用,表示集合中的元素均为协议类型,下面的例子创建了一个类型为`TextRepresentable`的数组:
协议类型可以在数组或者字典这样的集合使用,在[协议类型](./22_Protocols.html##protocols_as_types)提到了这样的用法。下面的例子创建了一个类型为`TextRepresentable`的数组:
```swift
let things: [TextRepresentable] = [game,d12,simonTheHamster]
@ -524,19 +527,20 @@ let things: [TextRepresentable] = [game,d12,simonTheHamster]
```swift
for thing in things {
print(thing.asText())
print(thing.textualDescription)
}
// 输出:
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon
```
`thing`被当做是`TextRepresentable`类型而不是`Dice``DiceGame``Hamster`等类型。因此能且仅能调用`asText`方法
`thing`被当做是`TextRepresentable`类型而不是`Dice``DiceGame``Hamster`等类型,即使真实的实例是它们中的一种类型。尽管如此,由于它是`TextRepresentable`类型,任何`TextRepresentable`都拥有一个`textualDescription`属性,所以每次循环访问`thing.textualDescription`是安全的。
<a name="protocol_inheritance"></a>
## 协议的继承
协议能够继承一个或多个其他协议,可以在继承的协议基础上增加新的内容要求。协议的继承语法与类的继承相似,多个被继承的协议间用逗号分隔:
协议能够继承一个或多个其他协议,可以在继承的协议基础上增加新的内容要求。协议的继承语法与类的继承相似,多个被继承的协议间用逗号分隔
```swift
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
@ -544,22 +548,22 @@ protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
}
```
如下所示,`PrettyTextRepresentable`协议继承了`TextRepresentable`协议
如下所示,`PrettyTextRepresentable`协议继承了`TextRepresentable`协议
```swift
protocol PrettyTextRepresentable: TextRepresentable {
func asPrettyText() -> String
var prettyTextualDescription: String { get }
}
```
例子中定义了一个新的协议`PrettyTextRepresentable`,它继承自`TextRepresentable`协议。任何遵循`PrettyTextRepresentable`协议的类型在满足该协议的要求时,也必须满足`TextRepresentable`协议的要求。在这个例子中,`PrettyTextRepresentable`协议要求其遵循者提供一个返回值为`String`类型的`asPrettyText`方法
例子中定义了一个新的协议`PrettyTextRepresentable`,它继承自`TextRepresentable`协议。任何遵循`PrettyTextRepresentable`协议的类型在满足该协议的要求时,也必须满足`TextRepresentable`协议的要求。在这个例子中,`PrettyTextRepresentable`协议要求其遵循者提供一个返回值为`String`类型的`prettyTextualDescription`属性
如下所示,扩展`SnakesAndLadders`,让其遵循`PrettyTextRepresentable`协议:
如下所示,扩展`SnakesAndLadders`,让其遵循`PrettyTextRepresentable`协议
```swift
extension SnakesAndLadders: PrettyTextRepresentable {
func asPrettyText() -> String {
var output = asText() + ":\n"
var prettyTextualDescription: String {
var output = textualDescription + ":\n"
for index in 1...finalSquare {
switch board[index] {
case let ladder where ladder > 0:
@ -575,17 +579,17 @@ extension SnakesAndLadders: PrettyTextRepresentable {
}
```
上述扩展使得`SnakesAndLadders`遵循了`PrettyTextRepresentable`协议,并为每个`SnakesAndLadders`类型提供了协议要求的`asPrettyText()`方法。每个`PrettyTextRepresentable`类型同时也是`TextRepresentable`类型,所以在`asPrettyText`的实现中,可以调用`asText()`方法。之后在每一行加上换行符,作为输出的开始。然后遍历数组中的元素,输出一个几何图形来表示遍历的结果:
上述扩展使得`SnakesAndLadders`遵循了`PrettyTextRepresentable`协议,并为每个`SnakesAndLadders`类型提供了协议要求的`prettyTextualDescription`属性。每个`PrettyTextRepresentable`类型同时也是`TextRepresentable`类型,所以在`prettyTextualDescription`的实现中,可以调用`textualDescription`属性。之后在每一行加上换行符,作为输出的开始。然后遍历数组中的元素,输出一个几何图形来表示遍历的结果:
* 当从数组中取出的元素的值大于0时`▲`表示
* 当从数组中取出的元素的值小于0时`▼`表示
* 当从数组中取出的元素的值等于0时`○`表示
任意`SankesAndLadders`的实例都可以使用`asPrettyText()`方法
任意`SankesAndLadders`的实例都可以使用`prettyTextualDescription`属性
```swift
print(game.asPrettyText())
// A game of Snakes and Ladders with 25 squares:
print(game.prettyTextualDescription)
// A game of Snakes and Ladders with 25 squares:TODO
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○
```
@ -595,14 +599,12 @@ print(game.asPrettyText())
```swift
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
// class-only protocol definition goes here
// 协议定义
}
```
在以上例子中,协议`SomeClassOnlyProtocol`只能被类class类型适配。如果尝试让结构体或枚举类型适配该协议则会出现编译错误。
<!--TODO 链接-->
>注意
>当协议想要定义的行为,要求(或假设)它的遵循类型必须是引用语义而非值语义时,应该采用类专属协议。关于引用语义,值语义的更多内容,请查看[结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types)和[类是引用类型](./09_Classes_and_Structures.html#classes_are_reference_types)。
@ -612,7 +614,7 @@ protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
有时候需要同时遵循多个协议。你可以将多个协议采用`protocol<SomeProtocol AnotherProtocol>`这样的格式进行组合,称为`协议合成(protocol composition)`。你可以在`<>`中罗列任意多个你想要遵循的协议,以逗号分隔。
下面的例子中,将`Named``Aged`两个协议按照上述的语法组合成一个协议:
下面的例子中,将`Named``Aged`两个协议按照上述的语法组合成一个协议
```swift
protocol Named {
@ -645,14 +647,13 @@ wishHappyBirthday(birthdayPerson)
<a name="checking_for_protocol_conformance"></a>
## 检验协议的一致性
<!--TODO 链接-->
你可以使用`is``as`操作符来检查是否遵循某一协议或强制转化为某一类型。检查和转化的语法和之前相同(*详情查看[类型转换](./20_Type_Casting.html)*):
* `is`操作符用来检查实例是否`遵循`了某个`协议`
* `as?`返回一个可选值,当实例`遵循`协议时,返回该协议类型;否则返回`nil`
* `is`操作符用来检查实例是否`遵循`了某个`协议`
* `as?`返回一个可选值,当实例`遵循`协议时,返回该协议类型;否则返回`nil`
* `as`用以强制向下转型,如果强转失败,会引起运行时错误。
下面的例子定义了一个`HasArea`的协议,要求有一个`Double`类型可读的`area`:
下面的例子定义了一个`HasArea`的协议,要求有一个`Double`类型可读的`area`
```swift
protocol HasArea {
@ -660,7 +661,7 @@ protocol HasArea {
}
```
如下所示,定义了`Circle``Country`类,它们都遵循了`HasArea`协议
如下所示,定义了`Circle``Country`类,它们都遵循了`HasArea`协议
```swift
class Circle: HasArea {
@ -677,7 +678,7 @@ class Country: HasArea {
`Circle`类把`area`实现为基于`存储型属性`radius的`计算型属性``Country`类则把`area`实现为`存储型属性`。这两个类都`遵循``HasArea`协议。
如下所示Animal是一个没有实现`HasArea`协议的类
如下所示,`Animal`是一个没有实现`HasArea`协议的类
```swift
class Animal {
@ -719,19 +720,16 @@ for object in objects {
<a name="optional_protocol_requirements"></a>
## 对可选协议的规定
协议可以含有可选成员,其`遵循者`可以选择是否实现这些成员。在协议中使用`optional`关键字作为前缀来定义可选成员。当需要使用可选规定的方法或者属性时,他的类型自动会变成可选的。比如,一个定义为`(Int) -> String`的方法变成`((Int) -> String)?`。需要注意的是整个函数定义包裹在可选中,而不是放在函数的返回值后面。
协议可以含有可选成员,其`遵循者`可以选择是否实现这些成员。在协议中使用`optional`关键字作为前缀来定义可选成员
<!--TODO 链接-->
可选协议在调用时使用`可选链`,因为协议的遵循者可能没有实现可选内容,详细内容在[可空链式调用](./17_Optional_Chaining.html)章节中查看。
`someOptionalMethod?(someArgument)`这样,你可以在可选方法名称后加上`?`来检查该方法是否被实现。可选方法和可选属性都会返回一个`可选值(optional value)`,当其不可访问时,`?`之后语句不会执行,并整体返回`nil`
可选协议在调用时使用`可选链`,因为协议的遵循者可能没有实现可选内容。像`someOptionalMethod?(someArgument)`这样,你可以在可选方法名称后加上`?`来检查该方法是否实现。详细内容在[可空链式调用](./17_Optional_Chaining.html)章节中查看
> 注意
> 可选协议只能在含有`@objc`前缀的协议中生效。且`@objc`的协议只能被`类`遵循
> 这个前缀表示协议将暴露给Objective-C代码详情参见`Using Swift with Cocoa and Objective-C`。即使你不打算和Objective-C有什么交互如果你想要指明协议包含可选属性那么还是要加上`@obj`前缀
> 可选协议只能在含有`@objc`前缀的协议中生效。
> 这个前缀表示协议将暴露给Objective-C代码详情参见[`Using Swift with Cocoa and Objective-C(Swift 2.1)`](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)。即使你不打算和Objective-C有什么交互如果你想要指明协议包含可选属性那么还是要加上`@obj`前缀
> 还需要注意的是,`@objc`的协议只能由继承自 Objective-C 类的类或者其他的`@objc`类来遵循。它也不能被结构体和枚举遵循。
下面的例子定义了一个叫`Counter`的整数加法类,它使用外部的数据源来实现每次的增量。数据源是两个可选属性,在`CounterDataSource`协议中定义:
下面的例子定义了一个叫`Counter`的整数加法类,它使用外部的数据源来提供每次的增量。数据源是两个可选规定,在`CounterDataSource`协议中定义
```swift
@objc protocol CounterDataSource {
@ -740,12 +738,12 @@ for object in objects {
}
```
`CounterDataSource`含有`incrementForCount`可选方法和`fiexdIncrement`可选属性,它们使用了不同的方法来从数据源中获取合适的增量值。
`CounterDataSource`含有`incrementForCount(_:)`可选方法和`fiexdIncrement`可选属性,它们使用了不同的方法来从数据源中获取合适的增量值。
> 注意
> `CounterDataSource`中的属性和方法都是可选的,因此可以在类中声明都不实现这些成员,尽管技术上允许这样做,不过最好不要这样写。
> 严格来讲,`CounterDataSource`中的属性和方法都是可选的,因此可以在类中声明都不实现这些成员,尽管技术上允许这样做,不过最好不要这样写。
`Counter`类含有`CounterDataSource?`类型的可选属性`dataSource`,如下所示:
`Counter`类含有`CounterDataSource?`类型的可选属性`dataSource`,如下所示
```swift
@objc class Counter {
@ -765,15 +763,16 @@ for object in objects {
`increment()`方法首先试图使用`incrementForCount(_:)`方法来得到每次的增量。`increment()`方法使用可选链来尝试调用`incrementForCount(_:)`,并将当前的`count`值作为参数传入。
这里使用了两种可选链方法。由于`dataSource`可能为`nil`,因此在`dataSource`后边加上了`?`标记来表明只在`dataSource`非空时才去调用`incrementForCount`方法。即使`dataSource`存在,但是也无法保证其是否实现了`incrementForCount`方法,因此在`incrementForCount`方法后边也加有`?`标记。
这里使用了两种可选链方法。首先,由于`dataSource`可能为`nil`,因此在`dataSource`后边加上了`?`标记来表明只在`dataSource`非空时才去调用`incrementForCount(_:)`方法。其次,即使`dataSource`存在,也无法保证其是否实现了`incrementForCount(_:)`方法,因为这个方法是可选的。在这里,有可能未被实现的`incrementForCount(_:)`方法同样使用可选链进行调用。只有在`incrementForCount(_:)`存在的情况下才能调用`incrementForCount(_:)`-也就是说,它是`nil`的时候。这就是为什么要在`incrementForCount(_:)`方法后边也加有`?`标记的原因
调用`incrementForCount`方法在上述两种情形都有可能失败,所以返回值为*可选*`Int`类型。虽然在`CounterDataSource`中,`incrementForCount`被定义为一个非可选`Int`(non-optional),但是这里我们仍然需要返回*可选*`Int`类型。
调用`incrementForCount`方法后,`Int``可选值`通过`可选绑定(optional binding)`自动拆包并赋值给常量`amount`。如果可选值确实包含一个数值,这表示`delegate`和方法都存在,之后便将`amount`加到`count`上,增加操作完成。
调用`incrementForCount(_:)`方法在上述两种情形都有可能失败,所以返回值为*可选*`Int`类型。虽然在`CounterDataSource`中,`incrementForCount`被定义为一个非可选`Int`(non-optional),但是这里我们仍然需要返回*可选*`Int`类型。想获得更多的关于如何使用多可选链的操作的信息,请查阅[多层链接](./17_Optional_Chaining)
如果没有从`incrementForCount(_:)`获取到值,可能是`dataSource`为nil或者它并没有实现`incrementForCount`方法——那么`increment()`方法将试图从数据源的`fixedIncrement`属性中获取增量。`fixedIncrement`也是一个可选型,所以在属性名的后面添加`?`来试图取回可选属性的值。和之前一样,返回值为可选型
在调用`incrementForCount(_:)`方法后,`Int``可选值`通过`可选绑定(optional binding)`自动拆包并赋值给常量`amount`。如果可选值确实包含一个数值,这表示`delegate`方法都存在,之后便将`amount`加到`count`上,增加操作完成
`ThreeSource`实现了`CounterDataSource`协议,它实现来可选属性`fixedIncrement`,每次返回值`3`:
如果没有从`incrementForCount(_:)`获取到值,可能是`dataSource`为nil或者它并没有实现`incrementForCount(_:)`方法——那么`increment()`方法将试图从数据源的`fixedIncrement`属性中获取增量。`fixedIncrement`也是一个可选型,所以在属性名的后面添加`?`来试图取回可选属性的值。和之前一样,返回值为可选型,即使在`CounterDataSource`中定义的是一个非可选的`Int`类型的`fixedIncrement`属性。
`ThreeSource`实现了`CounterDataSource`协议,它实现来可选属性`fixedIncrement`,设置值为`3`:
```swift
@objc class ThreeSource: CounterDataSource {
@ -839,7 +838,7 @@ for _ in 1...5 {
使用扩展协议的方式可以为遵循者提供方法或属性的实现。通过这种方式,可以让你无需在每个遵循者中都实现一次,无需使用全局函数,你可以通过扩展协议的方式进行定义。
例如,可以扩展`RandomNumberGenerator`协议,让其提供`randomBool()`方法。该方法使用协议中要求的`random()`方法来实现:
例如,可以扩展`RandomNumberGenerator`协议,让其提供`randomBool()`方法。该方法使用`random()`方法返回一个随机的`Bool`值:
```swift
extension RandomNumberGenerator {
@ -866,12 +865,12 @@ print("And here's a random Boolean: \(generator.randomBool())")
> 注意
> 通过扩展协议提供的协议实现和可选协议规定有区别。虽然协议遵循者无需自己实现,通过扩展提供的默认实现,可以不是用可选链调用。
例如,`PrettyTextRepresentable`协议,继承`TextRepresentable`协议,可以为其提供一个默认的`asPrettyText()`方法来简化返回值
例如,`PrettyTextRepresentable`协议,继承`TextRepresentable`协议,可以为其提供一个默认的`prettyTextualDescription`属性,来简化访问`textualDescription`属性:
```swift
extension PrettyTextRepresentable {
func asPrettyText() -> String {
return asText()
var prettyTextualDescription: String {
return textualDescription
}
}
```
@ -880,19 +879,20 @@ extension PrettyTextRepresentable {
在扩展协议的时候,可以指定一些限制,只有满足这些限制的协议遵循者,才能获得协议扩展提供的属性和方法。这些限制写在协议名之后,使用`where`关键字来描述限制情况。([Where语句](./23_Generics.html#where_clauses))。:
例如,你可以扩展`CollectionType`协议,但是只适用于元素遵循`TextRepresentable`的情况:
例如,你可以扩展`CollectionType`协议,但是只适用于元素遵循`TextRepresentable`的情况
```swift
extension CollectionType where Generator.Element : TextRepresentable {
func asList() -> String {
return "(" + ", ".join(map({$0.asText()})) + ")"
var textualDescription: String {
let itemsAsText = self.map { $0.textualDescription }
return "[" + itemsAsText.joinWithSeparator(", ") + "]"
}
}
```
`asList()`方法将每个元素以`asText()`的方式表示,最后以逗号分隔接起来。
`textualDescription`属性将每个元素的文本描述以逗号分隔的方式连接起来。
现在我们来看`Hamster`,它遵循`TextRepresentable`:
现在我们来看`Hamster`,它遵循`TextRepresentable`协议:
```swift
let murrayTheHamster = Hamster(name: "Murray")
@ -901,10 +901,10 @@ let mauriceTheHamster = Hamster(name: "Maurice")
let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]
```
因为`Array`遵循`CollectionType`协议,数组的元素又遵循`TextRepresentable`协议,所以数组可以使用`asList()`方法得到数组内容的文本表示:
因为`Array`遵循`CollectionType`协议,数组的元素又遵循`TextRepresentable`协议,所以数组可以使用`textualDescription`属性得到数组内容的文本表示:
```swift
print(hamsters.asList())
print(hamsters.textualDescription)
// 输出 "(A hamster named Murray, A hamster named Morgan, A hamster named Maurice)"
```

View File

@ -228,6 +228,7 @@ let fromTheTop = stackOfStrings.pop()
```
下图展示了如何从栈中pop一个值的过程
![此处输入图片的描述](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/stackPoppedOneString_2x.png)
<a name="extending_a_generic_type"></a>

View File

@ -33,7 +33,7 @@ Swift 的“词法结构(*lexical structure*)”描述了能构成该语言
标识符(*identifiers*)可以由以下的字符开始:大写或小写的字母 `A``Z`、下划线 `_`、基本多文种平面(*Basic Multilingual Plane*)中的 Unicode 非组合字符以及基本多文种平面以外的非专用区(*Private Use Area*)字符。首字符之后,允许使用数字和 Unicode 字符组合。
使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 `` `。例如,`class` 不是合法的标识符,但可以使用 <code>\`class\`</code>。反引号不属于标识符的一部分,<code>\`x\`</code>`x` 表示同一标识符。
使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 \`。例如,`class` 不是合法的标识符,但可以使用 \`class\`。反引号不属于标识符的一部分,\`x\``x` 表示同一标识符。
闭包(*closure*)中如果没有明确指定参数名称,参数将被隐式命名为 `$0``$1``$2`等等。 这些命名在闭包作用域范围内是合法的标识符。

View File

@ -7,7 +7,8 @@
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[Lenhoon](https://github.com/Lenhoon)
> 翻译+校对:[Lenhoon](https://github.com/Lenhoon),
> [BridgeQ](https://github.com/WXGBridgeQ)
本页包含内容:
@ -473,11 +474,11 @@ plusOne(10)
在程序里使用*枚举声明(enumeration)*来引入一个枚举类型。
枚举声明有两种基本的形式,使用关键字`enum`来声明。枚举声明体使用从零开始的变量——叫做*枚举事件(enumeration cases)*,和任意数量的声明,包括计算型属性,实例方法,类型方法,构造器,类型别名,甚至其他枚举,结构体,和类。枚举声明不能包含析构器或者协议声明。
枚举声明有两种基本的形式,使用关键字`enum`来声明。枚举声明体使用从零开始的变量——叫做*枚举用例(enumeration cases)*,和任意数量的声明,包括计算型属性,实例方法,类型方法,构造器,类型别名,甚至其他枚举,结构体,和类。枚举声明不能包含析构器或者协议声明。
枚举类型可以采用任何数量的协议,但是这些协议不能从类,结构体和其他的枚举继承。
不像类或者结构体。枚举类型并不提供隐式的初始构造器,所有构造器必须显式的声明。构造器可以委托枚举中的其他构造器,但是构造过程仅当构造器将一个枚事件指定给`self`才全部完成。
不像类或者结构体。枚举类型并不提供隐式的初始构造器,所有构造器必须显式的声明。构造器可以委托枚举中的其他构造器,但是构造过程仅当构造器将一个枚举用例指定给`self`才全部完成。
和结构体类似但是和类不同,枚举是值类型:枚举实例在赋予变量或常量时,或者被函数调用时被复制。
更多关于值类型的信息,参见结构体和枚举都是[值类型(Structures and Enumerations Are Value Types)](TODO)一节。
@ -485,9 +486,9 @@ plusOne(10)
可以扩展枚举类型,正如在[扩展声明(Extension Declaration)](TODO)中讨论的一样。
<a name="enumerations_with_cases_of_any_type"></a>
###任意事件类型的枚举
###任意用例类型的枚举
如下的形式声明了一个包含任意类型枚举时间的枚举变量
如下的形式声明了一个包含任意类型枚举用例的枚举变量
> enum `enumeration name`: `adopted protocols`{
> case `enumeration case 1`
@ -496,36 +497,53 @@ plusOne(10)
这种形式的枚举声明在其他语言中有时被叫做*可识别联合(discrinminated)*。
这种形式中,每一个事件块由关键字`case`开始,后面紧接着一个或多个以逗号分隔的枚举事件。每一个事件名必须是独一无二的。每一个事件也可以指定它所存储的指定类型的值,这些类型在*关联值类型(associated values types)*的元组里被指定,立即书写在事件
名后。获得更多关于关联值类型的信息和例子,请查看[关联值(Associated Values)](TODO)一节。
这种形式中,每一个用例块由关键字`case`开始,后面紧接着一个或多个以逗号分隔的枚举用例。每一个用例名必须是独一无二的。每一个用例也可以指定它所存储的指定类型的值,这些类型在*关联值类型(associated values types)*的元组里被指定,立即书写在用例名后。
枚举有一个递归结构,就是说,枚举有着枚举类型自身实例的关联值的事件。然而,枚举类型的实例有值语义,意味着它们在内存中有着固定的位置。为了支持递归,编译器必需插入一个间接层
枚举用例也可以指定函数作为其存储的值,从而通过特定的关联值创建一个枚举实例。和真正的函数一样,你可以获取一个枚举用例的引用,然后在后续代码中调用它
为间接使用特殊的枚举事件,使用`indirect`声明修饰符标记。
```swift
enum Number {
case Integer(Int)
case Real(Double)
}
let f = Number.Integer
// f is a function of type (Int) -> Number
// f 是一个传入 Int 返回 Number 类型的函数
// Apply f to create an array of Number instances with integer values
// 利用函数 f 把一个整数数组转成 Number 数组
let evenInts: [Number] = [0, 2, 4, 6].map(f)
```
获得更多关于关联值类型的信息和例子,请查看[关联值(Associated Values)](TODO)一节。
枚举有一个递归结构,就是说,枚举有着枚举类型自身实例的关联值的用例。然而,枚举类型的实例有值语义,意味着它们在内存中有着固定的位置。为了支持递归,编译器必需插入一个间接层。
为间接使用特殊的枚举用例,使用`indirect`声明修饰符标记。
> enum Tree<T> {
> case Empty
> indirect case Node(value: T, left: Tree, right:Tree)
> }
为了间接的使用一个枚举的所有事件,使用`indirect`修饰符标记整个枚举-当枚举有许多事件且每个事件都需要使用`indirect`修饰符标记的时候这将非常便利。
为了间接的使用一个枚举的所有用例,使用`indirect`修饰符标记整个枚举-当枚举有许多用例且每个用例都需要使用`indirect`修饰符标记的时候这将非常便利。
一个被`indirect`修饰符标记的枚举事件必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的事件和没有关联值的事件的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的事件
一个被`indirect`修饰符标记的枚举用例必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的用例和没有关联值的用例的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的用例
<a name="enumerations_with_cases_of_a_raw-value_type"></a>
###使用原始值类型事件的枚举(Enumerations with Cases of a Raw-Value Type)
###使用原始值类型用例的枚举(Enumerations with Cases of a Raw-Value Type)
以下的形式声明了一个包含相同基础类型的枚举事件的枚举:
以下的形式声明了一个包含相同基础类型的枚举用例的枚举:
> enum `enumeration name`: `raw value type`, `adopted protocols`{
> case `enumeration case 1` = `raw value 1`
> case `enumeration case 2` = `raw value 2`
> }
在这种形式中,每一个事件块由`case`关键字开始,后面紧接着一个或多个以逗号分隔的枚举事件。和第一种形式的枚举事件不同,这种形式的枚举事件包含一个同类型的基础值,叫做*原始值(raw value)*。这些值的类型在*原始值类型(raw-value type)*中被指定,必须表示一个整数,浮点数,字符串,或者一个字符。特别是*原始值类型(raw-value type)*必需遵守`Equatable`类型的协议和下列形式中的一种字面量构造协议(literal-convertible protocols):整型字面量有`IntergerLiteralConvertible`,浮点行字面量有`FloatingPointLiteralConvertible`,包含任意数量字符的字符串型字面量有`StringLiteralConvertible`,仅包含一个单一字符的字符串型字面量有`ExtendedGraphemeClusterLiteralConvertible`。每一个事件必须有唯一的名字,必须有一个唯一的初始值。
在这种形式中,每一个用例块由`case`关键字开始,后面紧接着一个或多个以逗号分隔的枚举用例。和第一种形式的枚举用例不同,这种形式的枚举用例包含一个同类型的基础值,叫做*原始值(raw value)*。这些值的类型在*原始值类型(raw-value type)*中被指定,必须表示一个整数,浮点数,字符串,或者一个字符。特别是*原始值类型(raw-value type)*必需遵守`Equatable`类型的协议和下列形式中的一种字面量构造协议(literal-convertible protocols):整型字面量有`IntergerLiteralConvertible`,浮点行字面量有`FloatingPointLiteralConvertible`,包含任意数量字符的字符串型字面量有`StringLiteralConvertible`,仅包含一个单一字符的字符串型字面量有`ExtendedGraphemeClusterLiteralConvertible`。每一个用例必须有唯一的名字,必须有一个唯一的初始值。
如果初始值类型被指定为`Int`,则不必为事件显式的指定值,它们会隐式的被标为值`0,1,2`等。每一个没有被赋值的`Int`类型时间会隐式的赋予一个初始值,它们是自动递增的。
如果初始值类型被指定为`Int`,则不必为用例显式的指定值,它们会隐式的被标为值`0,1,2`等。每一个没有被赋值的`Int`类型时间会隐式的赋予一个初始值,它们是自动递增的。
```Swift
num ExampleEnum: Int {
@ -535,7 +553,7 @@ num ExampleEnum: Int {
在上面的例子中,`ExampleEnum.A`的值是`0``ExampleEnum.B`的值是`1`。因为`ExampleEnum.C`的值被显式的设定为`5`,因此`ExampleEnum.D`的值会自动增长为`6`
如果原始值类型被指定为`String`类型,你不用明确的为事件指定值,每一个没有指定的事件会隐式地用与事件名字相同的字符串指定。
如果原始值类型被指定为`String`类型,你不用明确的为用例指定值,每一个没有指定的用例会隐式地用与用例名字相同的字符串指定。
> enum WeekendDay: String {
> case Saturday, Sunday
@ -543,14 +561,14 @@ num ExampleEnum: Int {
在上面这个例子中,`WeekendDay.Saturday`的原始值是`"Saturday"`,`WeekendDay.Sunday`的原始值是`"Sunday"`
拥有多种事件的原始值类型的枚举含蓄地遵循定义在Swift标准库中的`RawRepresentable`协议。所以,它们拥有一个原始值(`rawValue`)属性和一个有着`init?(rawValue: RawValue)`签名的可失败构造器(a failable initializer)。可以使用原始值属性去取的枚举事件的原始值,就像在`ExampleEnum.B.rawValue`中一样。如果有一个事件符合,也可以使用原始值去找到一个符合的事件,通过调用枚举的可失败构造器,如`ExampleEnum(rawValue: 5)`,这个可失败构造器返回一个可选的事件。想得到更多的信息和关于原始值类型查看更多信息和获取初始值类型事件的信息,参阅初始值[原始值(Raw Values)](TODO)。
拥有多种用例的原始值类型的枚举含蓄地遵循定义在Swift标准库中的`RawRepresentable`协议。所以,它们拥有一个原始值(`rawValue`)属性和一个有着`init?(rawValue: RawValue)`签名的可失败构造器(a failable initializer)。可以使用原始值属性去取的枚举用例的原始值,就像在`ExampleEnum.B.rawValue`中一样。如果有一个用例符合,也可以使用原始值去找到一个符合的用例,通过调用枚举的可失败构造器,如`ExampleEnum(rawValue: 5)`,这个可失败构造器返回一个可选的用例。想得到更多的信息和关于原始值类型查看更多信息和获取初始值类型用例的信息,参阅初始值[原始值(Raw Values)](TODO)。
<a name="accessing_enumeration_cases"></a>
###获得枚举事件
###获得枚举用例
使用点(.)来引用枚举类型的事件,如`EnumerationType.EnumerationCase`。当枚举类型可以上下文推断出时,可以省略它(.仍然需要),参照枚举语法[(Enumeration Syntax)](TODO)和[显式成员表达(Implicit Member Expression)](TODO)。
使用点(.)来引用枚举类型的用例,如`EnumerationType.EnumerationCase`。当枚举类型可以上下文推断出时,可以省略它(.仍然需要),参照枚举语法[(Enumeration Syntax)](TODO)和[显式成员表达(Implicit Member Expression)](TODO)。
使用`switch`语句来检验枚举事件的值,正如使用[switch语句匹配枚举值Matching Enumeration Values with a Switch Statement)](TODO)一节描述的那样。枚举类型是模式匹配(pattern-matched)的,和其相反的是`switch`语句case块中枚举事件匹配,在[枚举事件类型(Enumeration Case Pattern)](TODO)中有描述。
使用`switch`语句来检验枚举用例的值,正如使用[switch语句匹配枚举值Matching Enumeration Values with a Switch Statement)](TODO)一节描述的那样。枚举类型是模式匹配(pattern-matched)的,和其相反的是`switch`语句case块中枚举用例匹配,在[枚举用例类型(Enumeration Case Pattern)](TODO)中有描述。
<a name="grammer_of_an_enumeration_declaration"></a>
> 枚举声明语法

View File

@ -6,7 +6,7 @@
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[KYawn](https://github.com/KYawn)
> 翻译+校对:[KYawn](https://github.com/KYawn)[小铁匠Linus](https://github.com/kevin833752)
本页内容包括:
@ -71,6 +71,9 @@
protocol MyProtocol {
// protocol definition
}
```
```swift
// Subsequent release renames MyProtocol
protocol MyRenamedProtocol {
// protocol definition
@ -80,14 +83,14 @@ protocol MyRenamedProtocol {
typealias MyProtocol = MyRenamedProtocol
```
你可以在一个单独的声明上使用多个`available`特性,以详细说明该声明在不同平台上的有效性。编译器只有在当前的目标平台和`available`特性中指定的平台匹配时,才会使用`available`特性
你可以在一个单独的声明上使用多个`available`特性,以详细说明该声明在不同平台上的有效性。编译器只有在当前的目标平台和`available`特性中指定的平台匹配时,才会使用`available`特性。
如果`available`特性除了平台名称参数外,只指定了一个`introduced `参数,那么可以使用以下简写语法代替:
@available(`platform name` `version number`, *)
`available`特性的简写语法可以简明地表达出多个平台的可用性。尽管这两种形式在功能上是相同的,但请尽可能地使用简明语法形式。
```swift
@available(iOS 8.0, OSX 10.10, *)
class MyClass {
@ -107,7 +110,7 @@ class MyClass {
```swift
@objc
class ExampleClass {
class ExampleClass: NSObject {
var enabled: Bool {
@objc(isEnabled) get {
// Return the appropriate value
@ -138,7 +141,7 @@ class ExampleClass {
在类上使用该特性表示该类是应用程序委托类,使用该特性与调用`NSApplicationMain(_:_:)`函数并且把该类的名字作为委托类的名字传递给函数的效果相同。
如果你不想使用这个特性,可以提供一个`main.swift`文件,并且提供一个`main`函数去调用`NSApplicationMain(_:_:)`函数。比如,如果你的应用程序使用一个派生于`NSApplication`的自定义子类作为主要类,你可以调用`NSApplicationMain`函数而不是使用该特性。
如果你不想使用这个特性,可以提供一个`main.swift`文件,并且提供一个`main()`函数去调用`NSApplicationMain(_:_:)`函数。比如,如果你的应用程序使用一个派生于`NSApplication`的自定义子类作为主要类,你可以调用`NSApplicationMain`函数而不是使用该特性。
`NSCopying`
@ -148,7 +151,7 @@ class ExampleClass {
`NSManaged`
该特性用于修饰`NSManagedObject`子类中的存储型变量属性表明属性的存储和实现由Core Data在运行时基于相关实体描述动态提供。
该特性用于修饰`NSManagedObject`子类中的实例方法或存储型变量属性表明属性的存储和实现由Core Data在运行时基于相关实体描述动态提供。对于标记了`NSManaged`特性的属性Core Data也会在运行时提供存储。
`testable`
@ -164,16 +167,15 @@ class ExampleClass {
该特性应用于方法或函数声明,当方法或函数被调用,但其结果未被使用时,该特性会让编译器会产生警告。
你可以使用这个特性提供一个警告信息,这个警告信息是关于不正确地使用未变异的方法,这个方法也有一个对应的变异方法。
你可以使用这个特性提供一个警告信息,这个警告信息是关于不正确地使用未变异的方法,这个方法也有一个对应的变异方法。
`warn_unused_result`有下面两个可选的参数
`warn_unused_result`特性会有选择地采用下面两个参数之一
- `message`参数用来提供警告信息,并在因当方法或函数被调用,但其结果未被使用时,显示警告信息。格式如下:
- `message`参数用来提供警告信息。在当方法或函数被调用,但其结果未被使用时,显示警告信息。格式如下:
<p>`message=message`<p>这里的`message`由一个字符串文字构成。
- `mutable_variant`参数用于提供变异方法的名称,如果未变异方法以一个可变的值被调用而且其结果并未被使用时,应该使用此变异方法。格式如下(方法名有字符串构成):<p>`mutable_variant=method name`<p>
比如Swift标准库提供了变异方法`sortInPlace()`和未变异方法`sort()`集合,它们的元素生成器符合`Comparable`协议。如果你调用了`sort()`方法,而没有使用它的结果,很有可能,你打算使用变异方法`sortInPlace()`替代。
比如Swift标准库同时提供了变异方法`sortInPlace()`和未变异方法`sort()`集合,它们的元素生成器符合`Comparable`协议。如果你调用了`sort()`方法,而没有使用它的结果,其实很有可能,你是打算使用变异方法`sortInPlace()`
### Interface Builder使用的声明特性
@ -190,7 +192,7 @@ Interface Builder特性是Interface Builder用来与Xcode同步的声明特性
该特性用于函数的类型,它指出函数调用的约定。
`convention`特性有下面几个可选的参数
`convention`特性总是与下面的参数之一一起出现
- `swift`参数用于表明一个Swift函数引用。这是Swift中标准的函数值调用约定。
@ -205,14 +207,14 @@ Interface Builder特性是Interface Builder用来与Xcode同步的声明特性
该特性用于修饰函数或方法的类型,表明该函数或方法不会返回到它的调用者中去。你也可以用它标记函数或方法的声明,表示函数或方法的相应类型,`T`,是`@noreturn T`
> 特性语法
> *特性* → **@** [*特性名*](#attribute_name) [*特性参数子句*](#attribute_argument_clause) <sub>_可选_</sub>
> *特性* → **@** [*特性名*](#attribute_name) [*特性参数子句*](#attribute_argument_clause) (可选)
> *特性名* → [*标识符*](02_Lexical_Structure.html#identifiers)
> *特性参数子句* → **(** [*平衡令牌列表*](#balanced_tokens) <sub>_可选_</sub> **)**
> *特性(Attributes)列表* → [*特色*](#attribute) [*特性(Attributes)列表*](#attributes) <sub>_可选_</sub>
> *平衡令牌列表* → [*平衡令牌*](#balanced_token) [*平衡令牌列表*](#balanced_tokens) <sub>_可选_</sub>
> *平衡令牌* → **(** [*平衡令牌列表*](#balanced_tokens) <sub>_可选_</sub> **)**
> *平衡令牌* → **[** [*平衡令牌列表*](#balanced_tokens) <sub>_可选_</sub> **]**
> *平衡令牌* → **{** [*平衡令牌列表*](#balanced_tokens) <sub>_可选_</sub> **}**
> *特性参数子句* → **(** [*平衡令牌列表*](#balanced_tokens) (可选) **)**
> *特性(Attributes)列表* → [*特色*](#attribute) [*特性(Attributes)列表*](#attributes) (可选)
> *平衡令牌列表* → [*平衡令牌*](#balanced_token) [*平衡令牌列表*](#balanced_tokens) (可选)
> *平衡令牌* → **(** [*平衡令牌列表*](#balanced_tokens) (可选) **)**
> *平衡令牌* → **[** [*平衡令牌列表*](#balanced_tokens) (可选) **]**
> *平衡令牌* → **{** [*平衡令牌列表*](#balanced_tokens) (可选) **}**
> *平衡令牌* → **任意标识符, 关键字, 字面量或运算符**
> *平衡令牌* → **任意标点除了(, ), [, ], {, 或 }**

View File

@ -6,7 +6,8 @@
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[ray16897188](https://github.com/ray16897188)
> 翻译+校对:[ray16897188](https://github.com/ray16897188),
> [BridgeQ](https://github.com/WXGBridgeQ)
本页内容包括:
@ -132,7 +133,7 @@ let (a): Int = 2 // a: Int = 2
<a name="optional_pattern"></a>
## 可选模式Optional Pattern
可选模式与封装在一个`Optional(T)`或者一个`ExplicitlyUnwrappedOptional(T)`枚举中的`Some(T)`用例相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。
可选模式与封装在一个`Optional(Wrapped)`或者一个`ExplicitlyUnwrappedOptional(Wrapped)`枚举中的`Some(Wrapped)`用例相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。
由于可选模式是`optional``ImplicitlyUnwrappedOptional`枚举用例模式的语法糖syntactic sugar下面的2种写法是一样的

View File

@ -170,7 +170,8 @@ Program ended with exit code: 0
- 如果小伙伴们现在用的是Beta版的Xcode注意苹果官方Blog中在代码第17行如果在Xcode Beta4下是错误的这里的协议是LogicValue而不是BooleanVue所以记得看错误提示才是好习惯。
- 注意代码第34行完美支持if判断且输出结果为“老码请你吃火锅”老码也是说说而已请不要当真。
</a><a name="support-all-type"></a>
<a name="support-all-type"></a>
####支持兼容各们各派的类型
小伙伴们江湖风险门派众多老码有自己的OCBool类型可能嵩山少林有自己的SSBool类型甚至连郭美美都可能有自己的MMBool类型所以OCBool必须能够识别这些类型这些各门各派的类型只要支持LogicValue协议就应该可以被识别看老码怎么做

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB