技术控

    今日:126| 主题:49390
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] Swift 3

[复制链接]
相思劫 发表于 2016-10-4 15:17:27
93 5

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
Swift 3 正式发布已经 3 周了,大家 Swift 项目的代码迁移做的怎么样?Glow Baby 项目我花了近 3 天时间,12956 行增改,9817 行删减,360 个文件。迁移的过程是痛苦的,心很累,Xcode 8 的迁移工具也没有让我轻松多少。
  不过待迁移完毕后,Swift 3 读起来、写起来都更舒服。Swift 1 确立了语言的基线:安全、快速、现代。Swift 2 展现了 Swift 应该是什么,未来怎么走:面向协议的编程、开源。而 Swift 3 更多是清扫和规范:新的 API 设计简洁干净,减少了歧义;移除了很多 C 风格语法使代码风格更加一致,可读性更高。总体上说,Swift 3 更加优秀。我们来看看 从语言使用的角度上,Swift 3 到底有哪些改变和新特性。
  API 设计指南

  先来看看可能是改动行数最多的一个变化:API 的重命名和规范。新的 API 设计强调了 API    调用时的清晰,因为方法和属性只会声明一次,但反复调用。在保持语义、避免歧义的前提下,尽量简洁,减少冗余。  
  比如:
  避免歧义

  方法名中应该要包含所有需要的单词以减少阅读时的困惑,比如从一个 List 中移除指定位置的一个元素:
  1. extension List {  
  2.         public mutating func remove(at position: Index) -> Element
  3. }
  4. employees.remove(at: x)
复制代码
如果省略方法名中的    at,读代码的时候就不明确到底是删掉    x,还是删掉所在的位置    x的元素。  
  删除协议名字的    Type后缀  

  如原来的    CollectionType变成    Collection;一些特殊的情况下,加上    Protocol后缀避免歧义,如原来的    ErrorType变为    ErrorProtocol。  
  删除冗余的词

  如:
      Sequence.minElement()=>    Sequence.min()  
      UIColor.blackColor()=>    UIColor.black  
  根据 Side Effect 来决定命名

  Mutating 方法的命名应该是一个动词,而 non-mutating 应该用    ed/ing形式的词。如    array.sort()是对 array 本身进行排序,而    array.sorted()则是返回一个新的 Array。  
  很多方法的名字都大大缩短,比如原来    stringByAppendingString(aString: String)变成    appending(_ aString: String)。  
  还有很多条目这里不一一列举,感兴趣的可以官方的    Design Guidelines  
  引用 Objective-C 和 C 代码

  Objective-C Constants

  很多 Objective-C Constants 在 Swift 里成了 Enum。比如    HKQuantityTypeIdentifier:  
  1. enum HKQuantityTypeIdentifier : String {  
  2.         case bodyMassIndex
  3.         case bodyFatPercentage
  4.         case height
  5.         case bodyMass
  6.         case leanBodyMass
  7. }
复制代码
这里顺便提一下,Swift 3 里的 Enum 都是小写字母开头。
  C APIs

  C 的 APIs 原来都是会全局的方法和变量,现在都引入为成员变量使用。如大家熟悉的 CGContext 在 Swift 3 里:
  1. context.lineWidth = 1  
  2. context.strokeColor = CGColor(gray: 0.5, alpha: 1.0)  
  3. context.drawPath(mode: .Stroke)
复制代码
同样 Dispatch 的 APIs 也更加 Swifty:
  1. let queue = DispatchQueue(label: "com.example.imagetransform")  
  2. queue.async {  
  3.         let smallImage = image.resize(to: rect)
  4.         DispatchQueue.main.async {
  5.                 imageView.image = smallImage
  6.         }
  7. }
  8. let delay = DispatchTime.now() + .seconds(60)  
  9. queue.after(when: delay) {  
  10.         // ...
  11. }
复制代码
语法

  C 风格的语法

  自增    ++跟 自减    --运算符被移除了。  
  C 风格的 for 循环(    for (int i = 0; i < array.count; i++))也不能使用了。  
  函数

  
       
  • 函数参数中      let的显式使用被移除了。   
  • 函数参数中      var被移除掉了。   
  •       inout调整为类型修饰,而不是参数名修饰:      func double(input: inout Int)   
  • 同      inout类似,      @noescape和      @autoclosure也转变为类型修饰:      func foo(f: @noescape () -> ()) {}   
  • 移除了 Curry 函数的声明语法。像      func foo(x: Int)(y: Int) -> Int这种语法应该用      func foo(x: Int) -> (y: Int) -> Int这种语法代替。  
  Enum

  Enum 有不少改动,最明显的改动是所有的成员都变成了小写。其次,在枚举当中,必须要在成员前加上左前缀点。之前只是在枚举外使用需要加,现在枚举内部对    self进行    switch,也一定要加,确保代码的一致性。  
  1. enum Season {  
  2.         case spring
  3.         case summer
  4.         case fall
  5.         case winter
  6.         var foo: String {
  7.                 switch self {
  8.                 case .spring:  return ...
  9.                 case .summer: return ...
  10.                 ...
  11.                 }
  12.         }
  13. }
复制代码
另一个改动是,有关联值的 enum,在 case 后可以声明多个成员:
  1. enum MyEnum {  
  2.         case case1(Int, Float)
  3.         case case2(Float, Int)
  4. }
  5. switch value {  
  6. case let .case(x, 2), let .case2(2, x):  
  7.         print(x)
  8. case .case1, .case2:  
  9.         break
  10. }
复制代码
访问级别

  在 Swift 3 之前,我们有三种访问级别:
  
       
  • 公开(public)   
  • 内部(internal)   
  • 私有(private)  
  默认的是 internal,表示这个成员只能在 module 内可见。如果要在 module 外使用,就要将其设置为 public。private 表示该私有成员只能够在其所在文件内可用。
  在 Swift 3 中,多了一种访问级别 fileprivate。fileprivate 的效果相同于之前的 private,而 private 表示只在其对应的作用域中可见。这让访问级别更加清晰。
  Where

  Generic 声明

  在 generic 声明中,where 语句被移到了最后。Swift 3 之前,我们可能这么声明一个 generic 的方法:
  1. func anyCommonElements<T : SequenceType, U : SequenceType where  
  2.         T.Generator.Element: Equatable,
  3.         T.Generator.Element == U.Generator.Element>(lhs: T, _ rhs: U) -> Bool {
  4.     ...
  5. }
复制代码
Swift 3 中,正确的语法应该是:
  1. func anyCommonElements<T : SequenceType, U : SequenceType>(lhs: T, _ rhs: U) -> Bool  
  2.         where
  3.                 T.Generator.Element: Equatable,
  4.                 T.Generator.Element == U.Generator.Element {
  5.         ...
  6. }
复制代码
条件判断

  where 在条件判断语句中被删掉,取而代之的是逗号。原来这样的一个 guard 判断:
  1. guard let x = opt1, y = opt2 where x == y else {}
复制代码
在 Swift 3 中应该写成:
  1. guard let x = opt1, y = opt2, x == y else {}
复制代码
Implicitly Unwrapped Optional

  原来隐式解析 Optional 类型没有了,但其语法还在。
  1. enum HKQuantityTypeIdentifier : String {  
  2.         case bodyMassIndex
  3.         case bodyFatPercentage
  4.         case height
  5.         case bodyMass
  6.         case leanBodyMass
  7. }0
复制代码
     x的声明后面有个    !,看起来像个 IUO,但其实是一个 optional 类型。    x赋值给    y,y 是    Int?,因为这里不需要进行强制的解析。但    z是一个    Int,因为这里需要解析 x 里的值才能进行加法运算。  
  Tips

  在我进行 Swift 3 升级的过程中,遇到不少坑,有的很难测试出来,甚至导致我们需要重新提交一个新的版本。
  首先,Enum 的成员从大写变成小写。乍看起来没什么问题,但如果你的代码中有用到 String Raw 类型的 Enum,并且存储了它的 rawValue 的话,你代码升级后再把值取出来可能就有问题。比如 Season Enum 的例子:如果原来你把    Season.Spring.rawValue存起来,比如 User Defaults 里。现在你再拿出来    Season(rawValue: {springRawValue}),会得到一个 nil,因为新的 rawValue 都是小写。  
  另外一个是 Json Dictionary 声明的变化,原来 Json Dictionary 的类型通常是    [String: AnyObject]。而在 Swift 3,则是用    [String: Any]。Any 包括 optional 类型,而当你要是用    NSJSONSerialization.dataWithJSONObject对含有 Optional 类型的 Dictionary 序列化的话,就会有 runtime error 抛出。  
  以上是印象深刻的两个问题,其他问题 code 不同,可能会有不一样的表现,这里也不一一举例。
  总结

  升级 Swift 3 的过程虽然痛苦,也难以避免伴随着不少 bug 的出现,但熬过这个之后,Code 看起来写起来都会更加畅快。之后的 Swift 版本不大可能再出现这种规模的迁移。Swift 4 我们可能回看到完整泛型,并发,以及更多有趣,强大的特性。期待。
友荐云推荐




上一篇:Code in the wild to infect millions of IoT devices for crippling DDoS attacks
下一篇:Sourcegraph: the best way to read code just got better
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

remzc 发表于 2016-10-4 16:30:17
我是研究僧
回复 支持 反对

使用道具 举报

liyanglawyer 发表于 2016-10-11 21:17:37
总有一天我会骄傲的对你说:滚,我不需要你。
回复 支持 反对

使用道具 举报

ygiun 发表于 2016-10-12 18:13:48
大声告诉我这是几楼?
回复 支持 反对

使用道具 举报

冯强 发表于 2016-11-13 15:15:22
边撸边过
回复 支持 反对

使用道具 举报

蒋倩 发表于 2016-11-13 17:56:32
看完了这么强的文章,我想说点什么,但是又不知道说什么好,想来想去还是想想就好了
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表