diff --git a/source/README.md b/source/README.md index 9b5da07a..252787d3 100755 --- a/source/README.md +++ b/source/README.md @@ -1,4 +1,4 @@ -# 2.0 新的开始 +# 2.0 新的开始 > Swift 兴趣交流群:`131595168`, `146932759`, `151336833`, `153549217`. **加入一个群即可,请勿重复添加** @@ -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) 在我没有任何回复的情况下,不到一天时间,有五位朋友报名。看到这些回复的时候我真的很惊讶,也很感动,无论这个项目存在多少问题,只要有人关注,有人愿意为它付出,那我还有什么理由放弃呢? @@ -51,28 +49,28 @@ 下次你再打开这篇文档,可以多看看那些列在最上方的ID,哪怕不去follow和star,只是看一眼就好。他们的所有努力和付出,就存在于这短暂的一瞥中。 -Swift 2.0 参与者名单(按照章节顺序): -- [xtymichael](https://github.com/xtymichael) -- [AlanMelody](https://github.com/AlanMelody) -- [DianQK](https://github.com/DianQK) -- [dreamkidd](https://github.com/dreamkidd) -- [100mango](https://github.com/100mango) -- [futantan](https://github.com/futantan) -- [SkyJean](https://github.com/SkyJean) -- [yangsiy](https://github.com/yangsiy) -- [shanksyang](https://github.com/shanksyang) -- [chenmingbiao](https://github.com/chenmingbiao) -- [Channe](https://github.com/Channe) -- [lyojo](https://github.com/lyojo) -- [SergioChan](https://github.com/SergioChan) -- [mmoaay](https://github.com/mmoaay) -- [buginux](https://github.com/buginux) -- [KYawn](https://github.com/KYawn) -- [EudeMorgen](https://github.com/EudeMorgen) -- [littledogboy](https://github.com/littledogboy) -- [Lenhoon](https://github.com/Lenhoon) -- [ray16897188](https://github.com/ray16897188) -- [wardenNScaiyi](https://github.com/wardenNScaiyi) -- [miaosiqi](https://github.com/miaosiqi) +Swift 2.0 参与者名单(按照章节顺序): +- [xtymichael](https://github.com/xtymichael) +- [AlanMelody](https://github.com/AlanMelody) +- [DianQK](https://github.com/DianQK) +- [dreamkidd](https://github.com/dreamkidd) +- [100mango](https://github.com/100mango) +- [futantan](https://github.com/futantan) +- [SkyJean](https://github.com/SkyJean) +- [yangsiy](https://github.com/yangsiy) +- [shanksyang](https://github.com/shanksyang) +- [chenmingbiao](https://github.com/chenmingbiao) +- [Channe](https://github.com/Channe) +- [lyojo](https://github.com/lyojo) +- [SergioChan](https://github.com/SergioChan) +- [mmoaay](https://github.com/mmoaay) +- [buginux](https://github.com/buginux) +- [KYawn](https://github.com/KYawn) +- [EudeMorgen](https://github.com/EudeMorgen) +- [littledogboy](https://github.com/littledogboy) +- [Lenhoon](https://github.com/Lenhoon) +- [ray16897188](https://github.com/ray16897188) +- [wardenNScaiyi](https://github.com/wardenNScaiyi) +- [miaosiqi](https://github.com/miaosiqi) -最后,感谢极客学院提供的wiki系统,在国内访问起来速度很快,优化后的样式看起来也更舒服。 \ No newline at end of file +最后,感谢[极客学院](http://wiki.jikexueyuan.com)提供的wiki系统,在国内访问起来速度很快,优化后的样式看起来也更舒服。 \ No newline at end of file diff --git a/source/chapter1/02_a_swift_tour.md b/source/chapter1/02_a_swift_tour.md index 6d91a479..823358e2 100755 --- a/source/chapter1/02_a_swift_tour.md +++ b/source/chapter1/02_a_swift_tour.md @@ -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") ``` > 练习: @@ -730,4 +730,4 @@ anyCommonElements([1, 2, 3], [3]) > 练习: > 修改`anyCommonElements(_:_:)`函数来创建一个函数,返回一个数组,内容是两个序列的共有元素。 -` `和``是等价的。 +``和``是等价的。 diff --git a/source/chapter1/03_revision_history.md b/source/chapter1/03_revision_history.md index d6bdfea0..c734c5a4 100644 --- a/source/chapter1/03_revision_history.md +++ b/source/chapter1/03_revision_history.md @@ -2,7 +2,7 @@ --- -> 翻译:[成都老码团队翻译组-Arya](http://weibo.com/littlekok/) +> 翻译:[成都老码团队翻译组-Arya](http://weibo.com/littlekok/) > 校对:[成都老码团队翻译组-Oberyn](http://weibo.com/u/5241713117) 本页内容包括: @@ -23,7 +23,7 @@ - [XCode6 Beta4 Swift语法文档更新](#xcode6_beta4) - [XCode6 Beta3 Swift语法文档更新](#xcode6_beta3) - [XCode6 Beta2 Swift语法文档更新](#xcode6_beta2) -- [XCode6 Beta1 Swift语法文档更新](#xcode6_beta1) +- [XCode6 Beta1 Swift语法文档更新](#xcode6_beta1) - XCode6下载: [老码云盘下载](http://pan.baidu.com/disk/home#from=share_pan_logo&path=%252F%25E8%2580%2581%25E7%25A0%2581%25E4%25BA%2591%25E7%259B%2598-XCode6%252FXCode6-Beta5) 以下部分是针对XCode6每一次Beta版本直至正式版发布,Swift语法部分的更新归类 @@ -35,20 +35,20 @@ - - + + - - + + + +
发布日期
发布日期 语法变更记录
2015-04-13
2015-04-13
    -
  • - XCode6.4包含了对于构建和调试基于iOS8.4 App的支持 +

  • + XCode6.4包含了对于构建和调试基于iOS8.4 App的支持
  • -
-
@@ -59,59 +59,60 @@ - - + + - - + + +
  • + Swift现在自身提供了一个Set集合类型,更多信息请看集合 + +
  • +
  • + @autoclosure现在是一个参数声明的属性,而不是参数类型的属性。这里还有一个新的参数声明属性@noescape。更多信息,请看属性声明 +
  • +
  • + 对于类型属性和方法现在可以使用static关键字作为声明描述符,更多信息,请看类型变量属性 +
  • +
  • + Swift现在包含一个as?as!的向下可失败类型转换运算符。更多信息,请看协议遵循性检查 +
  • +
  • + 增加了一个新的指导章节,它是关于字符串索引的 +
  • +
  • + 从溢出运算符中移除了溢出除运算符和求余溢出运算符 +
  • +
  • + 更新了常量和常量属性在声明和构造时的规则,更多信息,请看常量声明 +
  • +
  • + 更新了字符串字面量中Unicode标量集的定义,请看字符串字面量中的特殊字符 +
  • +
  • + 更新了区间运算符章节来提示当半开区间运算符含有相同的起止索引时,其区间为空。 +
  • +
  • + 更新了闭包引用类型章节来澄清对于变量的捕获规则 +
  • +
  • + 更新了值溢出章节来澄清有符号整数和无符号整数的溢出行为 +
  • +
  • + 更新了协议声明章节来澄清协议声明时的作用域和成员 +
  • +
  • + 更新了捕获列表章节来澄清对于闭包捕获列表中的弱引用和无主引用的使用语法。 +
  • +
  • + 更新了运算符章节来明确指明一些例子来说明自定义运算符所支持的特性,如数学运算符,各种符号,Unicode符号块等 +
  • + +
    发布日期
    发布日期 语法变更记录
    2015-4-8
    2015-4-8
      -
    • - Swift现在自身提供了一个Set集合类型,更多信息,请看集合 -

    • -
    • - @autoclosure现在是一个参数声明的属性,而不是参数类型的属性。这里还有一个新的参数声明属性@noescape。更多信息,请看属性声明 -

    • -
    • - 对于类型属性和方法现在可以使用static关键字作为声明描述符,更多信息,请看类型变量属性 -

    • -
    • - Swift现在包含一个as?as!的向下可失败类型转换运算符。更多信息,请看协议遵循性检查 -

    • -
    • - 增加了一个新的指导章节,它是关于字符串索引的 -

    • -
    • - 从溢出运算符中移除了溢出除运算符(&/)和求余溢出运算符(&%) -

    • -
    • - 更新了常量和常量属性在声明和构造时的规则,更多信息,请看常量声明 -

    • -
    • - 更新了字符串字面量中Unicode标量集的定义,请看字符串字面量中的特殊字符 -

    • -
    • - 更新了区间运算符章节来提示当半开区间运算符含有相同的起止索引时,其区间为空。 -

    • -
    • - 更新了闭包引用类型章节来澄清对于变量的捕获规则 -

    • -
    • - 更新了值溢出章节来澄清有符号整数和无符号整数的溢出行为 -

    • -
    • - 更新了协议声明章节来澄清协议声明时的作用域和成员 -

    • -
    • - 更新了捕获列表章节来澄清对于闭包捕获列表中的弱引用和无主引用的使用语法。 -

    • -
    • - 更新了运算符章节来明确指明一些例子来说明自定义运算符所支持的特性,如数学运算符,各种符号,Unicode符号块等 -

    • -
    -
    @@ -123,35 +124,35 @@ - - + + - - + + +
  • + 在运行时可能会失败的类型转换可以使用as?as!运算符,而确保不会失败的类型转换现在使用as运算符。更多信息,请看类型转换运算符 +
  • + +
    发布日期
    发布日期 语法变更记录
    2015-02-09
    2015-02-09
      -
    • - 在函数作用域中的常量声明时可以不被初始化,它必须在第一次使用前被赋值。更多的信息,请看常量声明 +

    • + 在函数作用域中的常量声明时可以不被初始化,它必须在第一次使用前被赋值。更多的信息,请看常量声明
    • -
    • - 在构造器中,常量属性有且仅能被赋值一次。更多信息,请看在构造过程中给常量属性赋值 +

    • + 在构造器中,常量属性有且仅能被赋值一次。更多信息,请看在构造过程中给常量属性赋值
    • -
    • - 多个可选绑定现在可以在if语句后面以逗号分隔的赋值列表的方式出现,更多信息,请看可选绑定 +

    • + 多个可选绑定现在可以在if语句后面以逗号分隔的赋值列表的方式出现,更多信息,请看可选绑定
    • -
    • - 一个可选链表达式必须出现在后缀表达式中 -

    • -
    • - 协议类型转换不再局限于@obj修饰的协议了 +

    • + 一个可选链表达式必须出现在后缀表达式中
    • -
    • - 在运行时可能会失败的类型转换可以使用as?as!运算符,而确保不会失败的类型转换现在使用as运算符。更多信息,请看类型转换运算符必 +

    • + 协议类型转换不再局限于@obj修饰的协议了
    • -
    -
    @@ -163,29 +164,30 @@ - - + + - - - + + +
    发布日期
    发布日期 语法变更记录
    2014-12-19
      -
    • - 在对Watch App做消息通知模拟调试时,第一个payload.apns文件将会被默认选择 -

    • -
    • - 在为Watch App使用asset catalog时,38mm和42mm尺寸的图片就会被使用 -

    • -
    • - 在做Watch App开发时,@IBAction属性支持WKInterfaceSwitchWKInterfaceSlider Swift类型了 -

    • -
    • - 现在可以通过Device窗口安装,删除和访问App容器中的数据了。 -

    • -
    -
    2014-12-19 +
      +
    • + 在对Watch App做消息通知模拟调试时,第一个payload.apns文件将会被默认选择 +
    • +
    • + 在为Watch App使用asset catalog时,38mm和42mm尺寸的图片就会被使用 +
    • +
    • + 在做Watch App开发时,@IBAction属性支持WKInterfaceSwitchWKInterfaceSlider Swift类型了 +
    • +
    • + 现在可以通过Device窗口安装,删除和访问App容器中的数据了。 +
    • +
    +
    @@ -197,20 +199,20 @@ - - + + - - + + + +
    发布日期
    发布日期 语法变更记录
    2014-12-10
    2014-12-10
      -
    • - 现在在Interface Builder中可以针对特定的Device设备自定义Watch应用的Layout布局了 +

    • + 现在在Interface Builder中可以针对特定的Device设备自定义Watch应用的Layout布局了
    • -
    -
    @@ -222,30 +224,30 @@ - - + + - - + + +
  • + 在工具集中增加了对WatchKit的支持: + 1)UI设计工具增加了Apple Watch应用的界面组件,通知和小部件。 + 2)增加了调试和性能统计功能 + 3)增加Apple Watch应用的模拟器帮助调试应用功能 +
  • +
  • + 为了使Apple Watch应用能够正常工作,一些具体的参数必须设置: + 1)WatchKit中扩展配置文件Info.plist中的NSExtensionAttributes配置项WKAppBundleIdentifier必须和WatchKit App中的通用配置文件中的属性CFBundleIdentifier项目保持一致。2)WatchKit中的CFBundleIdentifier配置项必须和WKCompanionAppBundleIdentifier中的配置项保持一致 +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-11-28
    2014-11-28
      -
    • - XCode6.2包含了iOS8.2 SDK,该SDK中包含WatchKit用来开发Apple Watch应用。 +

    • + XCode6.2包含了iOS8.2 SDK,该SDK中包含WatchKit用来开发Apple Watch应用。
    • -
    • - 在工具集中增加了对WatchKit的支持: - 1)UI设计工具增加了Apple Watch应用的界面组件,通知和小部件。 - 2)增加了调试和性能统计功能 - 3)增加Apple Watch应用的模拟器帮助调试应用功能 -

    • -
    • - 为了使Apple Watch应用能够正常工作,一些具体的参数必须设置: - 1)WatchKit中扩展配置文件Info.plist中的NSExtensionAttributes配置项WKAppBundleIdentifier必须和WatchKit App中的通用配置文件中的属性CFBundleIdentifier项目保持一致。2)WatchKit中的CFBundleIdentifier配置项必须和WKCompanionAppBundleIdentifier中的配置项保持一致 -

    • -
    -
    @@ -257,29 +259,29 @@ - - + + - - + + +
  • + 把纯正的Swift类对象实例赋值给AnyObject量不会再Crash了。 +
  • +
  • + 在泛型使用场景下,遵循了协议类要求的构造器方法或者类型方法可以直接调用继承类中的方法了。 +
  • +
  • + 修正了InterfaceBuild中如果图片名字含有“/”时,会在OSX10.10上Crash或者无法打开的问题 +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-12-2
    2014-12-2
      -
    • - 在SourceKit中一些导致Crash的常见问题被修复,比如名字冲突和遗留废弃数据的问题等。 +

    • + 在SourceKit中一些导致Crash的常见问题被修复,比如名字冲突和遗留废弃数据的问题等。
    • -
    • - 把纯正的Swift类对象实例赋值给AnyObject量不会再Crash了。 -

    • -
    • - 在泛型使用场景下,遵循了协议类要求的构造器方法或者类型方法可以直接调用继承类中的方法了。 -

    • -
    • - 修正了InterfaceBuild中如果图片名字含有“/”时,会在OSX10.10上Crash或者无法打开的问题 -

    • -
    -
    @@ -291,26 +293,26 @@ - - + + - - + + + +
    发布日期
    发布日期 语法变更记录
    2014-10-16
    2014-10-16 -
    @@ -322,20 +324,20 @@ - - + + - - + + + +
    发布日期
    发布日期 语法变更记录
    2014-09-15
    2014-09-15 -
    @@ -347,23 +349,23 @@ - - + + - - + + +
  • + 自定义运算符现在可以包含`?`字符,更新的运算符(Operators)章节描述了改进后的规则,并且从自定义运算符(Custom Operators)章节删除了重复的运算符有效字符集合 +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-09-09
    2014-09-09 -
    @@ -375,31 +377,32 @@ - - + + - - + + +
  • + 对于泛型的类库函数或接口统一从T!更换为T?T,这样使得语法更加严谨,明确了可能返回为空和不为空的情况 +
  • +
  • + 字符类型不能使用+运算法链接,可以以String(C1)+String(2) 的方式实现字符间链接 +
  • +
  • + 重写了Sort函数,解决了栈溢出的问题 +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-09-03
    2014-09-03
      -
    • - 实现了内部库的修改和适配,主要包括如下: - 1)大量内部类或者函数遵循Optional类型和协议 - 2)移除大部分函数返回类型隐式解封可选类型的使用 +

    • + 实现了内部库的修改和适配,主要包括如下: + 1)大量内部类或者函数遵循Optional类型和协议 + 2)移除大部分函数返回类型隐式解封可选类型的使用 +
    • -
    • - 对于泛型的类库函数或接口统一从T!更换为T?T,这样使得语法更加严谨,明确了可能返回为空和不为空的情况 -

    • -
    • - 字符类型不能使用+运算法链接,可以以String(C1)+String(2) 的方式实现字符间链接 -

    • -
    • - 重写了Sort函数,解决了栈溢出的问题 -

    • -
    -
    @@ -409,32 +412,32 @@ - - + + - - + + +
  • + 在章节协议中,增加新的小节:对构造器的规定(Initializer Requirements) +
  • +
  • + 在章节协议中,增加新的小节:类专属协议(class-only protocols) +
  • +
  • + 断言(assertions)现在可以使用字符串内插语法,并删除了文档中有冲突的注释 +
  • +
  • + 更新了连接字符串和字符(Concatenating Strings and Characters)小节来说明一个事实,那就是字符串和字符不能再用+号运算符或者复合加法运算符+=相互连接,这两种运算符现在只能用于字符串之间相连。请使用String类型的append方法在一个字符串的尾部增加单个字符 +
  • +
  • + 在声明特性(Declaration Attributes)章节增加了关于availability特性的一些信息 +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-08-18
    2014-08-18 -
    @@ -444,71 +447,71 @@ - - + + - - + + +
  • + 可选类型(Optionals) 若有值时,不再隐式的转换为 true,同样,若无值时,也不再隐式的转换为 false, 这是为了避免在判别 optional Bool 的值时产生困惑。 替代的方案是,用==!= 运算符显式地去判断Optinal是否是 nil,以确认其是否包含值。 +
  • +
  • + Swift新增了一个 Nil合并运算符(Nil Coalescing Operator) (a ?? b), 该表达式中,如果Optional a的值存在,则取得它并返回,若Optional anil,则返回默认值 b +
  • +
  • + 更新和扩展 字符串的比较(Comparing Strings) 章节,用以反映和展示'字符串和字符的比较',以及'前缀(prefix)/后缀(postfix)比较'都开始基于扩展字符集(extended grapheme clusters)规范的等价比较. +
  • +
  • + 现在,你可以通过 可选链(Optional Chaining)来:给属性设值,将其赋给一个下标脚注(subscript); 或调用一个变异(mutating)方法或运算符。对此,章节——通过可选链访问属性(Accessing Properties Through Optional Chaining)的内容已经被相应的更新。而章节——通过可选链调用方法(Calling Methods Through Optional Chaining中,关于检查方法调用是否成功的例子,已被扩展为展示如何检查一个属性是否被设值成功。 + +
  • +
  • + 在章节可选链中,增加一个新的小节 访问可选类型的下标脚注(Accessing Subscripts of Optional Type) +
  • +
  • + 更新章节 访问和修改数组(Accessing and Modifying an Array) 以标示:从该版本起,不能再通过+= 运算符给一个数组添加一个新的项。. 对应的替代方案是, 使append 方法, 或者通过+=运算符来添加一个只有一个项的数组(single-item Array).
  • +
  • + 添加了一个提示:在 范围运算符(Range Operators)中,比如, a...ba..<b ,起始值a不能大于结束值b. +
  • +
  • + 重写了继承(Inheritance) 这一章:删除了本章中关于构造器重写的介绍性报道;转而将更多的注意力放到新增的部分——子类的新功能,以及如何通过重写(overrides)修改已有的功能。另外,小节 重写属性的Getters和Setters(Overriding Property Getters and Setters) 中的例子已经被替换为展示如何重写一个 description 属性. (而关于如何在子类的构造器中修改继承属性的默认值的例子,已经被移到 构造过程(Initialization) 这一章.) +
  • +
  • + 更新了 构造器的继承与重写(Initializer Inheritance and Overriding) 小节以标示: 重写一个特定的构造器必须使用 override 修饰符. +
  • +
  • + 更新 Required构造器(Required Initializers) 小节以标示:required 修饰符现在需要出现在所有子类的required构造器的声明中, 而required构造器的实现,现在可以仅从父类自动继承。 +
  • +
  • + 中置(Infix)的 运算符函数(Operator Functions) 不再需要@infix 属性. +
  • +
  • + 前置和后置运算符(Prefix and Postfix Operators)@prefix@postfix 属性,已变更为 prefixpostfix 声明修饰符(declaration modifiers). +
  • +
  • + 增加一条注解:当Prefix和postfix运算符被作用于同一个操作数时,关于前置和后置运算符(Prefix and Postfix Operators)的顺序(postfix运算符会先被执行) +
  • +
  • + 在运算符函数(Operator functions)中, 组合赋值运算符(Compound Assignment Operators) 不再使用 @assignment 属性来定义函数. +
  • +
  • + 在这个版本中,在定义自定义操作符(Custom Operators) 时,修饰符(Modifiers)的出现顺序发生变化。比如, 现在,你该编写 prefix operator, 而不是 operator prefix. +
  • +
  • + 增加信息:关于dynamic 声明修饰符(declaration modifier),于章节 声明修饰符(Declaration Modifiers). +
  • +
  • + 增加信息:字面量Literals 的类型推导(type inference) +
  • +
  • + 为章节Curried Functions添加了更多的信息. +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-08-04
    2014-08-04 -
    @@ -518,59 +521,59 @@ - - + + - - + + - +
  • + 加入新的章节 权限控制(Access Control). +
  • +
  • + 更新了章节 字符串和字符(Strings and Characters) 用以表明,在Swift中,Character 类型现在代表的是扩展字符集(extended grapheme cluster)中的一个Unicode,为此,新增了小节 Extended Grapheme Clusters 。同时,为小节 Unicode标量(Unicode Scalars)字符串比较(Comparing Strings)增加了更多内容. +
  • +
  • + 更新章节字符串字面量(String Literals):在一个字符串中,Unicode标量(Unicode scalars) 以 \u{n}的形式来表示, n 是一个最大可以有8位的16进制数(hexadecimal digits) +
  • +
  • + NSString length 属性已被映射到Swift的内建 String类型。(注意,这两属性的类型是utf16Count,而非 utf16count). +
  • +
  • + Swift的内建 String 类型不再拥有 uppercaseStringlowercaseString 属性.其对应部分在章节 字符串和字符(Strings and Characters)已经被删除, 并且各种对应的代码用例也已被更新. +
  • +
  • + 加入新的章节 没有外部名的构造器参数(Initializer Parameters Without External Names). +
  • +
  • + 加入新的章节 Required构造器(Required Initializers). +
  • +
  • + 加入新的章节 可选元祖(函数)返回类型 (Optional Tuple Return Types). +
  • +
  • + 更新章节 类型标注(Type Annotations) :多个相关变量可以用“类型标注”(type annotaion)在同一行中声明为同一类型。 +
  • +
  • + @optional, @lazy, @final, @required 等关键字被更新为 optional, lazy, final, required 参见声明修饰符(Declaration Modifiers). +
  • +
  • + 更新整本书 —— 引用 ..< 作为区间运算符(Half-Open Range Operator) (取代原先的.. ). +
  • +
  • + 更新了小节 读取和修改字典(Accessing and Modifying a Dictionary)Dictionary 现在早呢更加了一个 Boolean型的属性: isEmpty +
  • +
  • + 解释了哪些字符(集)可被用来定义自定义操作符 (Custom Operators) +
  • +
  • + nil 和布尔运算中的 truefalse 现在被定义为字面量Literals. +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-07-21
    2014-07-21
    @@ -580,40 +583,41 @@ - - + + - - + + - +
  • + Swift 中的数组 (Array) 类型从现在起具备了完整的值语义。具体信息被更新到 集合的可变性(Mutability of Collections)数组(Arrays) 两小节,以反映这个新的变化. 此外,还解释了如何 给Strings, Arrays和Dictionaries进行赋值和拷贝 (Assignment and Copy Behavior for Strings, Arrays, and Dictionaries). +
  • +
  • + 数组类型速记语法(Array Type Shorthand Syntax)SomeType[].更新为[SomeType] +
  • +
  • + 加入新的小节:字典类型的速记语法(Dictionary Type Shorthand Syntax).: [KeyType: ValueType]. +
  • +
  • + 加入新的小节:字典键类型的哈希值(Hash Values for Dictionary Key Types). +
  • +
  • + 例子 闭包表达式 (Closure Expressions) 中使用新的全局函数 sorted 取代原先的全局函数 sort 去展示如何返回一个全新的数组. +
  • +
  • + 更新关于 结构体逐一成员构造器 (Memberwise Initializers for Structure Types) 的描述:即使结构体的成员没有默认值,逐一成员构造器也可以自动获得。 +
  • +
  • + 区间运算符(Half-Open Range Operator)..更新到..< +
  • +
  • + 添加一个例子 扩展一个泛型(Extending a Generic Type) +
  • + +
    发布日期
    发布日期 语法变更记录
    2014-07-7
    2014-07-7
    @@ -623,20 +627,21 @@ - - + + - - + + - +
  • + 发布新的文档用以详述Swift - 苹果公司针对iOS和OS X应用的全新开发语言 +
  • + + +
    发布日期
    发布日期 语法变更记录
    2014-07-7
    2014-07-7
      -
    • - 发布新的文档用以详述Swift - 苹果公司针对iOS和OS X应用的全新开发语言 -

    • -
    @@ -645,20 +650,20 @@ - - + + - - + + - +
  • + 苹果全球开发者大会WWDC2014召开,发布了苹果最新的开发语言Swift,并释放出XCode6 Beta1版本 +
  • + + +
    发布日期
    发布日期 语法变更记录
    2014-06-3
    2014-06-3
      -
    • - 苹果全球开发者大会WWDC2014召开,发布了苹果最新的开发语言Swift,并释放出XCode6 Beta1版本 -

    • -
    - diff --git a/source/chapter1/GuidedTour cn.playground.zip b/source/chapter1/GuidedTour cn.playground.zip new file mode 100644 index 00000000..ca6747f5 Binary files /dev/null and b/source/chapter1/GuidedTour cn.playground.zip differ diff --git a/source/chapter2/01_The_Basics.md b/source/chapter2/01_The_Basics.md index 5dd92c6d..842a85b8 100755 --- a/source/chapter2/01_The_Basics.md +++ b/source/chapter2/01_The_Basics.md @@ -6,7 +6,8 @@ > 校对:[lslxdx](https://github.com/lslxdx) > 2.0 -> 翻译+校对:[xtymichael](https://github.com/xtymichael) +> 翻译+校对:[xtymichael](https://github.com/xtymichael) +> 定稿:[shanks](http://codebuild.me) 本页包含内容: @@ -67,7 +68,7 @@ var currentLoginAttempt = 0 这两行代码可以被理解为: -“声明一个名字是`maximumNumberOfLoginAttempts`的新常量,并给它一个值`10`。然后,声明一个名字是`currentLoginAttempt`的变量并将它的值初始化为`0`.” +“声明一个名字是`maximumNumberOfLoginAttempts`的新常量,并给它一个值`10`。然后,声明一个名字是`currentLoginAttempt`的变量并将它的值初始化为`0`。” 在这个例子中,允许的最大尝试登录次数被声明为一个常量,因为这个值不会改变。当前尝试登录次数被声明为一个变量,因为每次尝试登录失败的时候都需要增加这个值。 @@ -172,7 +173,7 @@ print("The current value of friendlyWelcome is \(friendlyWelcome)") ## 注释 请将你的代码中的非执行文本注释成提示或者笔记以方便你将来阅读。Swift 的编译器将会在编译代码时自动忽略掉注释部分。 -Swift 中的注释与C 语言的注释非常相似。单行注释以双正斜杠(`//`)作为起始标记: +Swift 中的注释与 C 语言的注释非常相似。单行注释以双正斜杠(`//`)作为起始标记: ```swift // 这是一个注释 @@ -259,11 +260,11 @@ Swift 也提供了一个特殊的无符号类型`UInt`,长度与当前平台 ## 类型安全和类型推断 -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 { ## 元组 -元组(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)") ## 可选类型 -使用可选类型(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`或者什么都没有。) ### 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 { ### 可选绑定 -使用可选绑定(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 { ## 错误处理 -你可以使用错误处理(error handling)来应对程序执行中可能会遇到的错误条件。 +你可以使用*错误处理(error handling)*来应对程序执行中可能会遇到的错误条件。 相对于可选中运用值的存在与缺失来表达函数的成功与失败,错误处理可以推断失败的原因,并传播至程序的其他部分。 @@ -747,7 +748,7 @@ do { ## 断言 -可选类型可以让你判断值是否存在,你可以在代码中优雅地处理值缺失的情况。然而,在某些情况下,如果值缺失或者值并不满足特定的条件,你的代码可能没办法继续执行。这时,你可以在你的代码中触发一个断言(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 时,断言会被禁用。 + ### 何时使用断言 当条件可能为假时使用断言,但是最终一定要_保证_条件为真,这样你的代码才能继续运行。断言的适用情景: diff --git a/source/chapter2/02_Basic_Operators.md b/source/chapter2/02_Basic_Operators.md index a850368b..41d5aad3 100755 --- a/source/chapter2/02_Basic_Operators.md +++ b/source/chapter2/02_Basic_Operators.md @@ -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" diff --git a/source/chapter2/03_Strings_and_Characters.md b/source/chapter2/03_Strings_and_Characters.md index 676b404d..65c635c3 100755 --- a/source/chapter2/03_Strings_and_Characters.md +++ b/source/chapter2/03_Strings_and_Characters.md @@ -25,17 +25,17 @@ `String`是例如"hello, world","albatross"这样的有序的`Character`(字符)类型的值的集合。通过`String`类型来表示。 -一个`String`的内容可以用变量的方式读取,它包括一个`Character`值的集合。 +一个`String`的内容可以用变量的方式读取,它包括一个`Character`值的集合。 创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。 字符串连接操作只需要简单地通过`+`符号将两个字符串相连即可。 -与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。你也可以在字符串内插过程中使用字符串插入常量、变量、字面量表达成更长的字符串,这样可以很容易的创建自定义的字符串值,进行展示、存储以及打印。 +与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。你也可以在字符串内插过程中使用字符串插入常量、变量、字面量表达成更长的字符串,这样可以很容易的创建自定义的字符串值,进行展示、存储以及打印。 尽管语法简易,但`String`类型是一种快速、现代化的字符串实现。 每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式(representations)。 你也可以在常量、变量、字面量和表达式中进行字符串插值操作,这可以帮助你轻松创建用于展示、存储和打印的自定义字符串。 -> 注意: +> 注意: > Swift 的`String`类型与 Foundation `NSString`类进行了无缝桥接。就像 [`AnyObject`类型](./19_Type_Casting.html#anyobject) 中提到的一样,在使用 Cocoa 中的 Foundation 框架时,您可以将创建的任何字符串的值转换成`NSString`,并调用任意的`NSString` API。您也可以在任意要求传入`NSString`实例作为参数的 API 中用`String`类型的值代替。 -> 更多关于在 Foundation 和 Cocoa 中使用`String`的信息请查看 *[Using Swift with Cocoa and Objective-C (Swift 2)](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)*。 +> 更多关于在 Foundation 和 Cocoa 中使用`String`的信息请查看 *[Using Swift with Cocoa and Objective-C (Swift 2)](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)*。 @@ -51,7 +51,7 @@ let someString = "Some string literal value" 注意`someString`常量通过字符串字面量进行初始化,Swift 会推断该常量为`String`类型。 -> 注意: +> 注意: 更多关于在字符串字面量中使用特殊字符的信息,请查看 [字符串字面量的特殊字符](#special_characters_in_string_literals) 。 @@ -90,7 +90,7 @@ constantString += " and another Highlander" // 这会报告一个编译错误 (compile-time error) - 常量字符串不可以被修改。 ``` -> 注意: +> 注意: 在 Objective-C 和 Cocoa 中,您需要通过选择两个不同的类(`NSString`和`NSMutableString`)来指定字符串是否可以被修改。 @@ -167,7 +167,7 @@ welcome.append(exclamationMark) // welcome 现在等于 "hello there!" ``` -> 注意: +> 注意: 您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。 @@ -190,7 +190,7 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" 该表达式计算`Double(multiplier) * 2.5`的值并将结果 (`7.5`) 插入到字符串中。 在这个例子中,表达式写为`\(Double(multiplier) * 2.5)`并包含在字符串字面量中。 -> 注意: +> 注意: > 插值字符串中写在括号中的表达式不能包含非转义双引号 (`"`) 和反斜杠 (`\`),并且不能包含回车或换行符。 @@ -199,7 +199,7 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" Unicode 是一个国际标准,用于文本的编码和表示。 它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。 -Swift 的`String`和`Character`类型是完全兼容 Unicode 标准的。 +Swift 的`String`和`Character`类型是完全兼容 Unicode 标准的。 ### Unicode 标量(Unicode Scalars) @@ -232,7 +232,7 @@ let blackHeart = "\u{2665}" // ♥, Unicode 标量 U+2665 let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496 ``` - + ### 可扩展的字形群集(Extended Grapheme Clusters) 每一个 Swift 的`Character`类型代表一个可扩展的字形群。 @@ -265,7 +265,7 @@ let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ ```swift let enclosedEAcute: Character = "\u{E9}\u{20DD}" // enclosedEAcute 是 é⃝ -``` +``` 局部的指示符号的 Unicode 标量可以组合成一个单一的`Character`值,例如`REGIONAL INDICATOR SYMBOL LETTER U`(`U+1F1FA`)和`REGIONAL INDICATOR SYMBOL LETTER S`(`U+1F1F8`): @@ -294,16 +294,16 @@ print("unusualMenagerie has \(unusualMenagerie.characters.count) characters") var word = "cafe" print("the number of characters in \(word) is \(word.characters.count)") // 打印输出 "the number of characters in cafe is 4" - + word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301 - + print("the number of characters in \(word) is \(word.characters.count)") // 打印输出 "the number of characters in café is 4" ``` -> 注意: +> 注意: > 可扩展的字符群集可以组成一个或者多个 Unicode 标量。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果您正在处理一个长字符串,需要注意`characters`属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。 -> +> > 另外需要注意的是通过`characters`属性返回的字符数量并不总是与包含相同字符的`NSString`的`length`属性相同。`NSString`的`length`属性是利用 UTF-16 表示的十六位代码单元数字,而不是 Unicode 可扩展的字符群集。作为佐证,当一个`NSString`的`length`属性被一个Swift的`String`值访问时,实际上是调用了`utf16Count`。 @@ -345,7 +345,7 @@ greeting[greeting.endIndex] // error greeting.endIndex.successor() // error ``` -使用`characters`属性的`indices`属性会创建一个包含全部索引的范围(`Range`),用来在一个字符串中访问单个字符。 +使用`characters`属性的`indices`属性会创建一个包含全部索引的范围(`Range`),用来在一个字符串中访问单个字符。 ```swift for index in greeting.characters.indices { @@ -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`)和`�`(`DOG FACE`,Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示: ```swift let dogString = "Dog‼🐶" @@ -526,16 +526,16 @@ let dogString = "Dog‼🐶" 其为`String.UTF8View`类型的属性,`UTF8View`是无符号8位 (`UInt8`) 值的集合,每一个`UInt8`值都是一个字符的 UTF-8 表示: - + - - + + - - + + @@ -548,7 +548,7 @@ let dogString = "Dog‼🐶" - + @@ -583,16 +583,16 @@ print("") 其为`String.UTF16View`类型的属性,`UTF16View`是无符号16位 (`UInt16`) 值的集合,每一个`UInt16`都是一个字符的 UTF-16 表示:
    Character D
    U+0044
    o
    U+006F
    g
    U+0067

    U+203C
    🐶
    U+1F436

    U+203C
    🐶
    U+1F436
    UTF-8
    Code Unit
    UTF-8
    Code Unit
    68 111 103182
    PositionPosition 0 1 2
    - + - + - - + + @@ -601,7 +601,7 @@ print("") - + @@ -638,7 +638,7 @@ print("")
    Character D
    U+0044
    o
    U+006F
    g
    U+0067

    U+203C
    🐶
    U+1F436
    🐶
    U+1F436
    UTF-16
    Code Unit
    UTF-16
    Code Unit
    68 111 10356374
    PositionPosition 0 1 2
    - + @@ -646,8 +646,8 @@ print("") - - + + @@ -655,7 +655,7 @@ print("") - + diff --git a/source/chapter2/05_Control_Flow.md b/source/chapter2/05_Control_Flow.md index 0788e176..04768e79 100755 --- a/source/chapter2/05_Control_Flow.md +++ b/source/chapter2/05_Control_Flow.md @@ -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`,能够使游戏的逻辑更加清晰和易于理解。 -### 提前退出 +## 提前退出 像`if`语句一样,`guard`的执行取决于一个表达式的布尔值。我们可以使用`guard`语句来要求条件必须为真时,以执行`guard`语句后的代码。不同于`if`语句,一个`guard`语句总是有一个`else`分句,如果条件不为真则执行`else`分局中的代码。 @@ -746,7 +748,7 @@ greet(["name": "Jane", "location": "Cupertino"]) 它可以使你的代码连贯的被执行而不需要将它包在`else`块中,它可以使你处理违反要求的代码接近要求。 -### 检测API是否可用 +## 检测API是否可用 Swift 有内置支持去检查接口的可用性的,这可以确保我们不会不小心地使用对于当前部署目标不可用的API。 diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 89160fc9..81565015 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -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`类型。 多个成员值可以出现在同一行上,用逗号隔开: @@ -83,14 +83,14 @@ directionToHead = .East ```swift directionToHead = .South switch directionToHead { -case .North: - print("Lots of planets have a north") -case .South: - print("Watch out for penguins") -case .East: - print("Where the sun rises") -case .West: - print("Where the skies are blue") + case .North: + print("Lots of planets have a north") + case .South: + print("Watch out for penguins") + case .East: + print("Where the sun rises") + case .West: + print("Where the skies are blue") } // 输出 "Watch out for penguins” ``` @@ -119,19 +119,19 @@ default: ## 相关值(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位“产品代码”。最后一个数字是“检查”位,用来验证代码是否被正确扫描: -其他商品上标有 QR 码格式的二维码,它可以使用任何 ISO8859-1 字符,并且可以编码一个最多拥有 2,953 字符的字符串: +其他商品上标有 QR 码格式的二维码,它可以使用任何 ISO 8859-1 字符,并且可以编码一个最多拥有 2953 个字符的字符串: -对于库存跟踪系统来说,能够把 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,9 +260,9 @@ let possiblePlanet = Planet(rawValue: 7) // possiblePlanet 类型为 Planet? 值为 Planet.Uranus ``` -然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 +然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个**可选**的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 ->注意: +>注意: >原始值构造器是一个可失败构造器,因为并不是每一个原始值都有与之对应的枚举成员。更多信息请参见[可失败构造器](../chapter3/05_Declarations#failable_initializers) 如果你试图寻找一个位置为9的行星,通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil`: @@ -288,9 +287,9 @@ if let somePlanet = Planet(rawValue: positionToFind) { ## 递归枚举(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" ``` -该函数如果遇到纯数字,就直接返回该数字的值。如果遇到的是加法或乘法元算,则分别计算左边表达式和右边表达式的值,然后相加或相乘。 +该函数如果遇到纯数字,就直接返回该数字的值。如果遇到的是加法或乘法运算,则分别计算左边表达式和右边表达式的值,然后相加或相乘。 diff --git a/source/chapter2/10_Properties.md b/source/chapter2/10_Properties.md index 1a341cc0..fb806128 100755 --- a/source/chapter2/10_Properties.md +++ b/source/chapter2/10_Properties.md @@ -305,6 +305,7 @@ stepCounter.totalSteps = 896 > 注意: > 跟实例的存储属性不同,必须给存储型类型属性指定默认值,因为类型本身无法在初始化过程中使用构造器给类型属性赋值。 +> 存储型类型属性是延迟初始化的(lazily initialized),它们只有在第一次被访问的时候才会被初始化。即使它们被多个线程同时访问,系统也保证只会对其进行初始化一次,并且不需要对其使用 `lazy` 修饰符。 ###类型属性语法 diff --git a/source/chapter2/14_Initialization.md b/source/chapter2/14_Initialization.md index 0d99214f..31a9c054 100755 --- a/source/chapter2/14_Initialization.md +++ b/source/chapter2/14_Initialization.md @@ -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)。 -## 存储型属性的初始赋值 +## 设置存储型属性的初始值 -类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值。存储型属性的值不能处于一个未知的状态。 +类和结构体在创建实例时,必须为所有存储型属性设置合适的初始值。存储型属性的值不能处于一个未知的状态。 -你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。以下章节将详细介绍这两种方法。 +你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。以下小节将详细介绍这两种方法。 ->注意: -当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观测器(`property observers`)。 +>注意: +当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观察者(`property observers`)。 ### 构造器 @@ -67,7 +67,7 @@ print("The default temperature is \(f.temperature)° Fahrenheit") 如前所述,你可以在构造器中为存储型属性设置初始值。同样,你也可以在属性声明时为其设置默认值。 >注意: -如果一个属性总是使用同一个初始值,可以为其设置一个默认值。无论定义默认值还是在构造器中赋值,最终它们实现的效果是一样的,只不过默认值将属性的初始化和属性的声明结合的更紧密。使用默认值能让你的构造器更简洁、更清晰,且能通过默认值自动推导出属性的类型;同时,它也能让你充分利用默认构造器、构造器继承(后续章节将讲到)等特性。 +如果一个属性总是使用相同的初始值,那么为其设置一个默认值比每次都在构造器中赋值要好。两种方法的效果是一样的,只不过使用默认值让属性的初始化和声明结合的更紧密。使用默认值能让你的构造器更简洁、更清晰,且能通过默认值自动推导出属性的类型;同时,它也能让你充分利用默认构造器、构造器继承等特性(后续章节将讲到)。 你可以使用更简单的方式在定义结构体`Fahrenheit`时为属性`temperature`设置默认值: @@ -80,17 +80,17 @@ struct Fahrenheit { ## 自定义构造过程 -你可以通过输入参数和可选属性类型来定义构造过程,也可以在构造过程中修改常量属性。这些都将在后面章节中提到。 +你可以通过输入参数和可选属性类型来自定义构造过程,也可以在构造过程中修改常量属性。这些都将在后面章节中提到。 ### 构造参数 -你可以在定义构造器时提供构造参数,为其提供自定义构造所需值的类型和名字。构造器参数的功能和语法跟函数和方法参数相同。 +自定义`构造过程`时,可以在定义中提供构造参数,指定所需值的类型和名字。构造参数的功能和语法跟函数和方法的参数相同。 下面例子中定义了一个包含摄氏度温度的结构体`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." ### 构造过程中常量属性的修改 -只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。 +你可以在构造过程中的任意时间点修改常量属性的值,只要在构造过程结束时是一个确定的值。一旦常量属性被赋值,它将永远不可更改。 >注意: -对某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。 +对于类的实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。 -你可以修改上面的`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.)" ## 默认构造器 -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 { ## 可失败构造器 -如果一个类,结构体或枚举类型的对象,在构造自身的过程中有可能失败,则为其定义一个可失败构造器,是非常有必要的。这里所指的“失败”是指,如给构造器传入无效的参数值,或缺少某种所需的外部资源,又或是不满足某种必要的条件等。 +如果一个类、结构体或枚举类型的对象,在构造自身的过程中有可能失败,则为其定义一个可失败构造器,是非常有用的。这里所指的“失败”是指,如给构造器传入无效的参数值,或缺少某种所需的外部资源,又或是不满足某种必要的条件等。 为了妥善处理这种构造过程中可能会失败的情况。你可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在`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!` 构造器是否会触发构造失败? ##必要构造器 @@ -938,7 +957,7 @@ class SomeClass { } } ``` -当子类重写基类的必要构造器时,必须在子类的构造器前同样添加`required`修饰符以确保当其它类继承该子类时,该构造器同为必要构造器。在重写基类的必要构造器时,不需要添加`override`修饰符: +在子类重写父类的必要构造器时,必须在子类的构造器前也添加`required`修饰符,这是为了保证继承链上子类的构造器也是必要构造器。在重写父类的必要构造器时,不需要添加`override`修饰符: ```swift class SomeSubclass: SomeClass { diff --git a/source/chapter2/16_Automatic_Reference_Counting.md b/source/chapter2/16_Automatic_Reference_Counting.md index ca246151..55b76166 100755 --- a/source/chapter2/16_Automatic_Reference_Counting.md +++ b/source/chapter2/16_Automatic_Reference_Counting.md @@ -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 来管理你的应用程序的内存。 @@ -260,7 +260,14 @@ unit4A = nil ``` 上面的两段代码展示了变量`john`和`unit4A`在被赋值为`nil`后,`Person`实例和`Apartment`实例的析构函数都打印出“销毁”的信息。这证明了引用循环被打破了。 - + + + >注意: + 在使用垃圾收集的系统里,弱指针有时用来实现简单的缓冲机制,因为没有强引用的对象只会在内存压力触发垃圾收集时才被销毁。但是在 ARC 中,一旦值的最后一个强引用被删除,就会被立即销毁,这导致弱引用并不适合上面的用途。 + ### 无主引用 @@ -441,6 +448,20 @@ class HTMLElement { 默认情况下,闭包赋值给了`asHTML`属性,这个闭包返回一个代表 HTML 标签的字符串。如果`text`值存在,该标签就包含可选值`text`;如果`text`不存在,该标签就不包含文本。对于段落元素,根据`text`是`"some text"`还是`nil`,闭包会返回"`

    some text

    `"或者"`

    `"。 可以像实例方法那样去命名、使用`asHTML`属性。然而,由于`asHTML`是闭包而不是实例方法,如果你想改变特定元素的 HTML 处理的话,可以用自定义的闭包来取代默认值。 + + +例如,可以将一个闭包赋值给`asHTML`属性,这个闭包能在文本属性是 nil 时用默认文本,这是为了避免返回一个空的 `HTML` 标签: +```swift +let heading = HTMLElement(name: "h1") +let defaultText = "some default text" +heading.asHTML = { + return "<\(heading.name)>\(heading.text ?? defaultText)" +} +print(heading.asHTML()) +// prints "

    some default text

    " +``` > 注意: `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`。 ###定义捕获列表 diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md index ae8f74b0..4ae60072 100644 --- a/source/chapter2/22_Protocols.md +++ b/source/chapter2/22_Protocols.md @@ -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)`这个协议。 +除了遵循协议的类型必须实现那些指定的规定以外,还可以对协议进行扩展,实现一些特殊的规定或者一些附加的功能,使得遵循的类型能够收益。 ## 协议的语法 @@ -60,11 +63,11 @@ class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { ## 对属性的规定 -协议可以规定其`遵循者`提供特定名称和类型的`实例属性(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`。 ## 对方法的规定 协议可以要求其遵循者实现某些指定的实例方法或类方法。这些方法作为协议的一部分,像普通的方法一样放在协议的定义中,但是不需要大括号和方法体。可以在协议中定义具有可变参数的方法,和普通方法的定义方式相同。但是在协议的方法定义中,不支持参数默认值。 -正如对属性的规定中所说的,在协议中定义类方法的时候,总是使用`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 { > 注意 > 协议是一种类型,因此协议类型的名称应与其他类型(Int,Double,String)的写法相同,使用大写字母开头的驼峰式写法,例如(`FullyNamed`和`RandomNumberGenerator`) -如下所示,这个示例中将协议当做类型来使用 +如下所示,这个示例中将协议当做类型来使用: ```swift class Dice { @@ -329,9 +332,9 @@ for _ in 1...5 { ## 委托(代理)模式 -委托是一种设计模式,它允许`类`或`结构体`将一些需要它们负责的功能`交由(委托)`给其他的类型的实例。委托模式的实现很简单: 定义协议来封装那些需要被委托的函数和方法, 使其`遵循者`拥有这些被委托的`函数和方法`。委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的类型信息。 +委托是一种设计模式,它允许`类`或`结构体`将一些需要它们负责的功能`交由(或委托)`给其他的类型的实例。委托模式的实现很简单: 定义协议来封装那些需要被委托的函数和方法,使其`遵循者`拥有这些被委托的`函数和方法`。委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的类型信息。 -下面的例子是两个基于骰子游戏的协议: +下面的例子是两个基于骰子游戏的协议: ```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 轮 ``` @@ -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" ``` > 注意 -> 即使满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出显式的协议声明 +> 即使满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出显式的协议声明。 -## 集合中的协议类型 +## 协议类型的集合 -协议类型可以在集合使用,表示集合中的元素均为协议类型,下面的例子创建了一个类型为`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`是安全的。 ## 协议的继承 -协议能够继承一个或多个其他协议,可以在继承的协议基础上增加新的内容要求。协议的继承语法与类的继承相似,多个被继承的协议间用逗号分隔: +协议能够继承一个或多个其他协议,可以在继承的协议基础上增加新的内容要求。协议的继承语法与类的继承相似,多个被继承的协议间用逗号分隔: ```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)类型适配。如果尝试让结构体或枚举类型适配该协议,则会出现编译错误。 - - >注意 >当协议想要定义的行为,要求(或假设)它的遵循类型必须是引用语义而非值语义时,应该采用类专属协议。关于引用语义,值语义的更多内容,请查看[结构体和枚举是值类型](./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`这样的格式进行组合,称为`协议合成(protocol composition)`。你可以在`<>`中罗列任意多个你想要遵循的协议,以逗号分隔。 -下面的例子中,将`Named`和`Aged`两个协议按照上述的语法组合成一个协议: +下面的例子中,将`Named`和`Aged`两个协议按照上述的语法组合成一个协议: ```swift protocol Named { @@ -645,14 +647,13 @@ wishHappyBirthday(birthdayPerson) ## 检验协议的一致性 - 你可以使用`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 { ## 对可选协议的规定 +协议可以含有可选成员,其`遵循者`可以选择是否实现这些成员。在协议中使用`optional`关键字作为前缀来定义可选成员。当需要使用可选规定的方法或者属性时,他的类型自动会变成可选的。比如,一个定义为`(Int) -> String`的方法变成`((Int) -> String)?`。需要注意的是整个函数定义包裹在可选中,而不是放在函数的返回值后面。 -协议可以含有可选成员,其`遵循者`可以选择是否实现这些成员。在协议中使用`optional`关键字作为前缀来定义可选成员。 - - -可选协议在调用时使用`可选链`,因为协议的遵循者可能没有实现可选内容,详细内容在[可空链式调用](./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)" ``` diff --git a/source/chapter2/23_Generics.md b/source/chapter2/23_Generics.md index 2d34fe26..360458e0 100644 --- a/source/chapter2/23_Generics.md +++ b/source/chapter2/23_Generics.md @@ -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) diff --git a/source/chapter3/02_Lexical_Structure.md b/source/chapter3/02_Lexical_Structure.md index c2acd335..1be68adc 100755 --- a/source/chapter3/02_Lexical_Structure.md +++ b/source/chapter3/02_Lexical_Structure.md @@ -33,7 +33,7 @@ Swift 的“词法结构(*lexical structure*)”描述了能构成该语言 标识符(*identifiers*)可以由以下的字符开始:大写或小写的字母 `A` 到 `Z`、下划线 `_`、基本多文种平面(*Basic Multilingual Plane*)中的 Unicode 非组合字符以及基本多文种平面以外的非专用区(*Private Use Area*)字符。首字符之后,允许使用数字和 Unicode 字符组合。 -使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 `` `。例如,`class` 不是合法的标识符,但可以使用 \`class\`。反引号不属于标识符的一部分,\`x\` 和 `x` 表示同一标识符。 +使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 \`。例如,`class` 不是合法的标识符,但可以使用 \`class\`。反引号不属于标识符的一部分,\`x\` 和 `x` 表示同一标识符。 闭包(*closure*)中如果没有明确指定参数名称,参数将被隐式命名为 `$0`、`$1`、`$2`等等。 这些命名在闭包作用域范围内是合法的标识符。 diff --git a/source/chapter3/05_Declarations.md b/source/chapter3/05_Declarations.md index 541dbef4..7a66795a 100755 --- a/source/chapter3/05_Declarations.md +++ b/source/chapter3/05_Declarations.md @@ -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)中讨论的一样。 -###任意事件类型的枚举 +###任意用例类型的枚举 -如下的形式声明了一个包含任意类型枚举时间的枚举变量 +如下的形式声明了一个包含任意类型枚举用例的枚举变量 > 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 { > case Empty > indirect case Node(value: T, left: Tree, right:Tree) > } -为了间接的使用一个枚举的所有事件,使用`indirect`修饰符标记整个枚举-当枚举有许多事件且每个事件都需要使用`indirect`修饰符标记的时候这将非常便利。 +为了间接的使用一个枚举的所有用例,使用`indirect`修饰符标记整个枚举-当枚举有许多用例且每个用例都需要使用`indirect`修饰符标记的时候这将非常便利。 -一个被`indirect`修饰符标记的枚举事件必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的事件和没有关联值的事件的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的事件。 +一个被`indirect`修饰符标记的枚举用例必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的用例和没有关联值的用例的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的用例。 -###使用原始值类型事件的枚举(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)。 -###获得枚举事件 +###获得枚举用例 -使用点(.)来引用枚举类型的事件,如`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)中有描述。 > 枚举声明语法 @@ -1057,4 +1075,4 @@ Swift提供了三个级别的权限控制:`public`, `internal`, 和 `private` >访问级别修饰符 → **public­** | **public­(­set­)­** > >访问级别修饰符 → [访问级别修饰符(access-level-modeifier)](TODO) [访问级别修饰符列表(access-level-modeifiers)](TODO) _可选_ -­ \ No newline at end of file +­ diff --git a/source/chapter3/06_Attributes.md b/source/chapter3/06_Attributes.md index aa81dcd4..21f5b989 100755 --- a/source/chapter3/06_Attributes.md +++ b/source/chapter3/06_Attributes.md @@ -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) 本页内容包括: @@ -70,7 +70,10 @@ // First release 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`特性的简写语法可以简明地表达出多个平台的可用性。尽管这两种形式在功能上是相同的,但请尽可能地使用简明语法形式。 +`available`特性的简写语法可以简明地表达出多个平台的可用性。尽管这两种形式在功能上是相同的,但请尽可能地使用简明语法形式。 + ```swift @available(iOS 8.0, OSX 10.10, *) class MyClass { @@ -107,11 +110,11 @@ 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`参数用来提供警告信息。在当方法或函数被调用,但其结果未被使用时,会显示警告信息。格式如下:

    `message=message`

    这里的`message`由一个字符串文字构成。 - `mutable_variant`参数用于提供变异方法的名称,如果未变异方法以一个可变的值被调用而且其结果并未被使用时,应该使用此变异方法。格式如下(方法名有字符串构成):

    `mutable_variant=method name`

    - -比如,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) _可选_ +> *特性* → **@** [*特性名*](#attribute_name) [*特性参数子句*](#attribute_argument_clause) (可选) > *特性名* → [*标识符*](02_Lexical_Structure.html#identifiers) -> *特性参数子句* → **(** [*平衡令牌列表*](#balanced_tokens) _可选_ **)** -> *特性(Attributes)列表* → [*特色*](#attribute) [*特性(Attributes)列表*](#attributes) _可选_ -> *平衡令牌列表* → [*平衡令牌*](#balanced_token) [*平衡令牌列表*](#balanced_tokens) _可选_ -> *平衡令牌* → **(** [*平衡令牌列表*](#balanced_tokens) _可选_ **)** -> *平衡令牌* → **[** [*平衡令牌列表*](#balanced_tokens) _可选_ **]** -> *平衡令牌* → **{** [*平衡令牌列表*](#balanced_tokens) _可选_ **}** +> *特性参数子句* → **(** [*平衡令牌列表*](#balanced_tokens) (可选) **)** +> *特性(Attributes)列表* → [*特色*](#attribute) [*特性(Attributes)列表*](#attributes) (可选) +> *平衡令牌列表* → [*平衡令牌*](#balanced_token) [*平衡令牌列表*](#balanced_tokens) (可选) +> *平衡令牌* → **(** [*平衡令牌列表*](#balanced_tokens) (可选) **)** +> *平衡令牌* → **[** [*平衡令牌列表*](#balanced_tokens) (可选) **]** +> *平衡令牌* → **{** [*平衡令牌列表*](#balanced_tokens) (可选) **}** > *平衡令牌* → **任意标识符, 关键字, 字面量或运算符** > *平衡令牌* → **任意标点除了(, ), [, ], {, 或 }** diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 056cdd22..d9aa54c2 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -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 ## 可选模式(Optional Pattern) -可选模式与封装在一个`Optional(T)`或者一个`ExplicitlyUnwrappedOptional(T)`枚举中的`Some(T)`用例相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。 +可选模式与封装在一个`Optional(Wrapped)`或者一个`ExplicitlyUnwrappedOptional(Wrapped)`枚举中的`Some(Wrapped)`用例相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。 由于可选模式是`optional`和`ImplicitlyUnwrappedOptional`枚举用例模式的语法糖(syntactic sugar),下面的2种写法是一样的: diff --git a/source/chapter4/02_Type_Custom.md b/source/chapter4/02_Type_Custom.md index 56ab7f12..b7d463b5 100644 --- a/source/chapter4/02_Type_Custom.md +++ b/source/chapter4/02_Type_Custom.md @@ -170,7 +170,8 @@ Program ended with exit code: 0 - 如果小伙伴们现在用的是Beta版的Xcode,注意苹果官方Blog中,在代码第17行如果在Xcode Beta4下是错误的,这里的协议是,LogicValue而不是BooleanVue,所以记得看错误提示才是好习惯。 - 注意代码第34行,完美支持if判断,且输出结果为“老码请你吃火锅”,老码也是说说而已,请不要当真。 - + + ####支持兼容各们各派的类型 小伙伴们,江湖风险,门派众多,老码有自己的OCBool类型,可能嵩山少林有自己的SSBool类型,甚至连郭美美都可能有自己的MMBool类型,所以OCBool必须能够识别这些类型,这些各门各派的类型,只要支持LogicValue协议,就应该可以被识别,看老码怎么做, diff --git a/swift 2.0引用图片/1.png b/swift 2.0引用图片/1.png deleted file mode 100644 index 20374e2d..00000000 Binary files a/swift 2.0引用图片/1.png and /dev/null differ diff --git a/swift 2.0引用图片/2.png b/swift 2.0引用图片/2.png deleted file mode 100644 index 8a90b39c..00000000 Binary files a/swift 2.0引用图片/2.png and /dev/null differ diff --git a/swift 2.0引用图片/3.png b/swift 2.0引用图片/3.png deleted file mode 100644 index 8ea56387..00000000 Binary files a/swift 2.0引用图片/3.png and /dev/null differ diff --git a/swift 2.0引用图片/4.png b/swift 2.0引用图片/4.png deleted file mode 100644 index 134628c4..00000000 Binary files a/swift 2.0引用图片/4.png and /dev/null differ diff --git a/swift 2.0引用图片/5.png b/swift 2.0引用图片/5.png deleted file mode 100644 index a0a2db6b..00000000 Binary files a/swift 2.0引用图片/5.png and /dev/null differ diff --git a/swift 2.0引用图片/6.png b/swift 2.0引用图片/6.png deleted file mode 100644 index 4ad5a41e..00000000 Binary files a/swift 2.0引用图片/6.png and /dev/null differ

    Character D
    U+0044
    o
    U+006F

    U+203C
    🐶
    U+1F436
    UTF-16
    Code Unit
    UTF-16
    Code Unit
    68 111 103128054
    PositionPosition 0 1 2