Any vs AnyObject
将项目里的 AnyObject 转成 Any 可能是大家遇到的第一件适配大事。如何解释这个变化呢?在 Swift 3 之前,我们可以写完一个项目都只用 AnyObject 来代表大多数实例,好像不用与 Any 类型打交道。但事实上,Any 和 AnyObject 是有明显区别的,因为 Any 可以代表 struct、class、func 等等几乎所有类型,而 AnyObject 只能代表 class 生成的实例。
那为什么之前我们在 Swift 2 里可以用 [AnyObject] 声明数组,并且在里面放 Int、String 等 struct 类型呢?这是因为 Swift 2 中,会针对这些 Int、String 等 struct 进行一个 Implicit Bridging Conversions,在 Array 里插入他们时,编译器会自动将其 bridge 到 Objective-C 的 NSNumber、NSString 等类型,这就是为什么我们声明的 [AnyObject] 里可以放 struct 的原因。
但在 Swift 3 当中,为了达成一个门真正的跨平台语言,相关提案将 Implicit Bridging Conversions 给去掉了。所以如果你要把 String 这个 struct 放进一个 [AnyObject] 里,一定要 as NSString,这些转换都需要显示的进行了——毕竟 Linux 平台默认没有 Objective-C runtime。
@discardableResult 的使用
在 Swift 3 编译器下,如果一个 func 返回了一个对象,而你没有使用它时,会有一个 WARNING。对于追求项目洁癖(不想看到 1 个 WARNING 和 1 个 ERROR)的人来说这是不能忍的,尽管你可能是故意不去使用它的。
这里有两种方法可以解决这个 WARNING。
第一种:在 func 定义的前面,加上 @discardableResult 的修饰符,代表可以不使用返回值,这样编译器就不会有警告了。在我们自己定义的 func 上基本上都可以这么做。
但是还会有一种情况,用了第三方库或者系统库返回的对象怎么办?那只能用第二种办法:
_ = navigationController?.popViewController(animated: true)
像这样通过 _ 来省略掉了。虽然比较难看,考虑到 Swift 是一门严格的语言,就忍忍吧。
Protocol 实现一定要在对应的 extension 里
以前写代码时会有不注意的地方,比如 UITableViewDelegate 和 UITableViewDataSource,我分别用 extension 来实现,但是在具体的实现中没注意,把 delegate 的一个方法放进了 dataSource 的 extension 去实现,项目也能完全正常运作。
但是在 Swift 3.0 下,如果你在一个 extension 里实现一个 protocol,那么这个 protocol 的方法一定要在这个 extension 里面能找到,而不能在另外一个 extension 里或者主 class 或 struct 里面。不然会有类似这样的警告:
Objective-C method ‘tableView:canEditRowAt:‘ provided by method ‘tableView(_:canEditRowAt:)‘ does not match the requirement‘s selector (‘tableView:canEditRowAtIndexPath:‘)
这也是 Swift 3 编译变得更严格的一个表现。
Implicitly Unwrapped Optionals 的坑
在 Swift 2 的项目中,我们可能存在这样不是特别安全的代码:
var greetings: String!
greetings = "Hello"
print("\(greetings) 图拉鼎")
这里会输出:
Hello 图拉鼎
没有任何问题。但是在 Swift 3 中,因为 Optional 的安全机制起作用了,会变成:
Optional("Hello") 图拉鼎
这个结果不是我们想要的。从这点也可以看到,Swift 3 的 IUO 行为变得更安全了,默认会把 IUO 变成 Optional。如果想要达到和 Swift 2 一样的效果,就得用:
print("\(greetings!) 图拉鼎")
这时你也注意到了,Swift 始终在用 ! 提醒你用 IUO 不那么安全。
Alamofire 最低支持iOS9
虽然说我使用的三方库都在第一时间将库升级到了 Swift 3 ,但是期中 Alamofire 库最低适配只支持到了 iOS 9。
参考:https://zhuanlan.zhihu.com/p/22584349