Swift 3 迁移适配总结

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看189 回复回复2 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 189|回复: 2
收起左侧

Swift 3 迁移适配总结

[复制链接]
移动 发表于 2016-10-30 13:21:28 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
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 到底有哪些改变和新特性。




1、API 设计指南

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

比如:



1.1、避免歧义

方法名中应该要包含所有需要的单词以减少阅读时的困惑,比如从一个 List 中移除指定位置的一个元素:

[Swift] 纯文本查看 复制代码
extension List {  
        public mutating func remove(at position: Index) -> Element
}
employees.remove(at: x)  


如果省略方法名中的 at,读代码的时候就不明确到底是删掉 x,还是删掉所在的位置 x 的元素。



1.2、删除协议名字的 Type 后缀

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



1.3、删除冗余的词

如:

[Swift] 纯文本查看 复制代码
Sequence.minElement() => Sequence.min()

UIColor.blackColor() => UIColor.black




1.4、根据 Side Effect 来决定命名

Mutating 方法的命名应该是一个动词,而 non-mutating 应该用 ed/ing 形式的词。如 array.sort() 是对 array 本身进行排序,而 array.sorted() 则是返回一个新的 Array。

很多方法的名字都大大缩短,比如原来 stringByAppendingString(aString: String) 变成 appending(_ aString: String)。

还有很多条目这里不一一列举,感兴趣的可以官方的 Design Guidelines




2、引用 Objective-C 和 C 代码



2.1、Objective-C Constants

很多 Objective-C Constants 在 Swift 里成了 Enum。比如 HKQuantityTypeIdentifier:

[Swift] 纯文本查看 复制代码
enum HKQuantityTypeIdentifier : String {  
        case bodyMassIndex
        case bodyFatPercentage
        case height
        case bodyMass
        case leanBodyMass
}


这里顺便提一下,Swift 3 里的 Enum 都是小写字母开头。



2.2、C APIs

C 的 APIs 原来都是会全局的方法和变量,现在都引入为成员变量使用。如大家熟悉的 CGContext 在 Swift 3 里:

[Swift] 纯文本查看 复制代码
context.lineWidth = 1  
context.strokeColor = CGColor(gray: 0.5, alpha: 1.0)  
context.drawPath(mode: .Stroke)  


同样 Dispatch 的 APIs 也更加 Swifty:

[Swift] 纯文本查看 复制代码
let queue = DispatchQueue(label: "com.example.imagetransform")  
queue.async {  
        let smallImage = image.resize(to: rect)
        DispatchQueue.main.async {
                imageView.image = smallImage
        }
}

let delay = DispatchTime.now() + .seconds(60)  
queue.after(when: delay) {  
        // ...
}





3、语法



3.1、C 风格的语法

自增 ++ 跟 自减 -- 运算符被移除了。

C 风格的 for 循环(for (int i = 0; i < array.count; i++) )也不能使用了。



3.2、函数

  • 函数参数中 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 这种语法代替。




3.3、Enum

Enum 有不少改动,最明显的改动是所有的成员都变成了小写。其次,在枚举当中,必须要在成员前加上左前缀点。之前只是在枚举外使用需要加,现在枚举内部对 self 进行 switch,也一定要加,确保代码的一致性。

[Swift] 纯文本查看 复制代码
enum Season {  
        case spring
        case summer
        case fall
        case winter

        var foo: String {
                switch self {
                case .spring:  return ...
                case .summer: return ...
                ...
                }
        }
}


另一个改动是,有关联值的 enum,在 case 后可以声明多个成员:

[Swift] 纯文本查看 复制代码
enum MyEnum {  
        case case1(Int, Float)
        case case2(Float, Int)
}

switch value {  
case let .case(x, 2), let .case2(2, x):  
        print(x)
case .case1, .case2:  
        break
}




3.4、访问级别

在 Swift 3 之前,我们有三种访问级别:

  • 公开(public)
  • 内部(internal)
  • 私有(private)


默认的是 internal,表示这个成员只能在 module 内可见。如果要在 module 外使用,就要将其设置为 public。private 表示该私有成员只能够在其所在文件内可用。

在 Swift 3 中,多了一种访问级别 fileprivate。fileprivate 的效果相同于之前的 private,而 private 表示只在其对应的作用域中可见。这让访问级别更加清晰。



3.5、Where


3.5.1、Generic 声明

在 generic 声明中,where 语句被移到了最后。Swift 3 之前,我们可能这么声明一个 generic 的方法:

[Swift] 纯文本查看 复制代码
func anyCommonElements<T : SequenceType, U : SequenceType where  
        T.Generator.Element: Equatable,
        T.Generator.Element == U.Generator.Element>(lhs: T, _ rhs: U) -> Bool {
    ...
}


Swift 3 中,正确的语法应该是:

[Swift] 纯文本查看 复制代码
func anyCommonElements<T : SequenceType, U : SequenceType>(lhs: T, _ rhs: U) -> Bool  
        where
                T.Generator.Element: Equatable,
                T.Generator.Element == U.Generator.Element {
        ...
}



3.5.2、条件判断

where 在条件判断语句中被删掉,取而代之的是逗号。原来这样的一个 guard 判断:

[Swift] 纯文本查看 复制代码
guard let x = opt1, y = opt2 where x == y else {}  


在 Swift 3 中应该写成:

[Swift] 纯文本查看 复制代码
guard let x = opt1, y = opt2, x == y else {}  




3.6、Implicitly Unwrapped Optional

原来隐式解析 Optional 类型没有了,但其语法还在。

[Swift] 纯文本查看 复制代码
let x: Int! = 5  
let y = x  
let z = x + 0  


x 的声明后面有个 !,看起来像个 IUO,但其实是一个 optional 类型。x 赋值给 y,y 是 Int?,因为这里不需要进行强制的解析。但 z 是一个 Int,因为这里需要解析 x 里的值才能进行加法运算。




4、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 不同,可能会有不一样的表现,这里也不一一举例。




5、总结

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



推荐再看看:

Swift 3 迁移工作总结

适配 Swift 3 的一点小经验和坑




作者:顾鹏

都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

本帖被以下淘专辑推荐:

不是我教你诈 发表于 2016-11-2 15:18:24 | 显示全部楼层
Side Effect
攻城狮 发表于 2016-11-8 09:48:05 | 显示全部楼层
隐式解析 Optional 类型没有了,但其语法还在。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
关闭

站长推荐 上一条 /3 下一条

热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表