Swift 3 新特性和迁移详解
写在前面
Swift 3.0 正式版发布了差不多快一个月了,断断续续的把手上和 Swift 相关的迁移到了Swift 3.0。所以写点小总结。
背景
代码量(4万行)
首先,我是今年年初才开始入手 Swift 的。加上 Swift 的 ABI 和 API 一直不稳定,所以没有在项目中大范围的使用,所以这次迁移的代码量不多,大概在4万行左右。
迁移时间(一天左右)
迁移时间上的话,大概是花了1天左右。两个混编项目,一个 Swift 为主的项目。期中 Swift 为主的项目 花了大概大半天时间,两个混编代码量差不多,但是一个花了小半天,还有一个差不多只花了半个小时(原因先留个悬念~)。
准备
在开发最初开发选择 Swift 的时候的很多决策也让我这次少了很多工作量。
界面用 xib 而不用纯代码
阴差阳错的,和 Swift 相关的大部分界面都是用xib 画的。而这个 xib 在这次迁移中得到了很大的优势,xib 和 SB 的代码不适配 Swift 3。想当初要是使用代码写的 UI 的话,这次迁移改动估计会多很多吧。
关于第三方库的选择:
对于一个项目来说,三方库似乎成了一道必选菜,但是如何去选择这道菜呢?
对于三方库,当初的选择是,能用 OC 就尽量用 OC。 毕竟可以OC 可以无缝衔接到 Swift,而且还相对稳定。
在选择 Swift 相关的三方库时,我尽量值选择使用者比较多的库,例如Alamofire、Snap、Kingfisher、Fabric等,因为使用者比较多,开发者会更愿意去维护,而不至于跳票。所以不会存在现在许多小伙伴面临的问题,想迁移,但是有些库没有更新。至少对于我来说,当我想迁移的时候,所有和 Swift 相关的三方库都已经迁移到了 3.0 了。
得益于上面两点,在迁移过程中少了不少工作量。????
知识储备升级
先了解了一下Swift 2 到 Swift 3 的变动,及变动的原因。(看完心中一万头草泥马飞过,但是其实是越来越好了)
然后把语法文档快速的重温了一遍。
迁移中的问题
Any && AnyObject
我想在做迁移和做完迁移的同学改的最多的一个就是
as AnyObjct?
吧?至少对于我来说是的。
和这个相关的基本是集合类型。在 Swift 2 中我们一个用 [AnyObject] 来存放任何变量,甚至于存放struct类型的
String
、Array
等。但是按道理 Swift 的 AnyObject 指的是类,而 Any 才是包括struct
、class
、func
等所有类型。但是为何 Struct 可以放入 [AnyObject] 呢?在 Swift 2 的时候会针对String、Int 等 Struct 进行一个 Implicit Bridging Conversions。而到了 Swift 3 则进行了一个**Fully eliminate implicit bridging conversions from Swift**改动。当然在我的项目中[AnyObject]其实是小事,最麻烦的就是 [String:AnyObject]。因为当初写项目的时候,还是处于 OC To Swift 的阶段所以对于 Dictionary ,基本采用了 [String:AnyObject], 所以在修改的时候,在很多地方为了这个修改。
起初,我是照着 Xcode 的提示,在 Dictionary 后面的 value 后面加了一个
as AnyObjct?
后来渐渐的发现我做了一件很傻比的事情,其实我只要把 [String:AnyObject] 改为 [String:Any] 就可以了。????
这也就是为什么在第一混编的项目中我花了那么多时间去修改代码了!得益于混编的第二个项目学习了 Yep 的思路,是把
[String:AnyObject]
命名为一个叫做JSONDictionary
的类型。所以在 Any && AnyObect 这个事情上,就花了一点点时间。
// Swift 2
var json = [String:AnyObect]()
json["key1"] = 1
json["key2"] = "2" // to Swift 3 Step 1
var json = [String:AnyObect]()
json["key1"] = 1 as AnyObject?
json["key2"] = "2" as AnyObject? // to Swift 3 Step 2
var json = [String:Any]()
json["key1"] = 1
json["key2"] = "2" // Swift 2
public typealias JSONDictionary = [String: AnyObject]
// To Swift 3 Step 2
public typealias JSONDictionary = [String: Any]
Alamofire 等三方库支持 iOS8
虽然说我使用的三方库都在第一时间将库升级到了 Swift 3 ,但是期中 Alamofire 和 Snap 两个库最低适配只支持到了 iOS 9,为了避免和产品撕逼,不得不想办法解决这个适配问题。下面以 Alamofire 为例
其实三方库么,不一定只用 Cocoapods 的。所以打算下载代码然后直接撸源码。
先Alamofire的 Xcode 修改为最低适配 8.0,然后编译查找不通过的函数,并删除。(其实这些函数都是 iOS 9 新加的函数,所以删除不影响什么。)
大概花了 半个小时左右就可以删完了,然后直接拖到项目中就可以了~
Snap 其实只要拖进去就好了,暂时不需要修改什么。
// 其实都是 !os(watchOS) 这个宏下面的
#if !os(watchOS) @discardableResult
public func stream(withHostName hostName: String, port: Int) -> StreamRequest {
return SessionManager.default.stream(withHostName: hostName, port: port)
} @discardableResult
public func stream(with netService: NetService) -> StreamRequest {
return SessionManager.default.stream(with: netService)
} #endif
@escaping
这个是我在适配中最蛋疼的坑
首先在看swift-evolution只是了解到@escaping 必须显示声明。但是不知道@escaping的闭包,在函数体内无法再修改。
let pedonmeter:CMPedometer = CMPedometer() func getPedometerDataFromDate(_ datet:Date?, withHandler handler: @escaping (CMPedometerData?, Error?) -> ()){ // 编译错误
pedonmeter.queryPedometerDataFromDate(startTime, toDate:endTime, withHandler: { (pedometerData:CMPedometerData?, error:NSError?) -> Void in guard let pedometerData = pedometerData else { return }
handler(pedometerData, error) // 做一些事情 })
// 最后逼不得已只能不修改了,函数外面就做一些事情了
pedonmeter.queryPedometerData(from: startTime, to: endTime, withHandler: handler as! CMPedometerHandler) }
Result of call to 'funtion' is unused
这其实不是一个 编译错误,但是这个警告最开始让我有点懵逼.返回值不用难道要我都修改一下?
最开始其实我是这么修改的
let _ = funtion()
,但是后面在看SE-0047的时候发现@discardableResult
也是可以达到这个效果的。
Date && NSDate
因为有个项目中使用的 DateTools 这个工具。它有一个 NSDate + Tools 的分类。
但是在写 Swift 3 的过程中我发现如果变量是 Date 类型的无法使用NSDate + Tools 这个类型,必须显示声明date as NSDate 这样才能调用分类的一些个方法。
这个让使用 OC 的库的时候会感觉十分不舒服,毕竟很多 NS 的前缀去掉了。所有都显示声明太不友好了。
CAAnimationDelegate
这个其实好像是 Xcode 8 的修改。因为之前CAAnimationDelegate 是一个分类。大概声明如下:
@interface NSObject (CAAnimationDelegate)- (void)animationDidStart:(CAAnimation *)anim;
-
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;@end
之前是在 vc 中只要重写一下
animationDidStart
函数就可以了。但是新的不行,起初以为是 Swift 3 的变化,但是其实是 Xcode 8 中的修改。将 CAAnimationDelegate 变成了一个协议。我感觉这个修改是为了适配 Swift 3 ?变化如下:
@protocol CAAnimationDelegate @optional- (void)animationDidStart:(CAAnimation *)anim;
-
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;@end
因为宽度时间比较长,其他的暂时想不到了。未完待续吧...
其他
还有许多微妙的变化让你似乎看不懂这个语言了,所以建议在适配之前看一下下面的文章。
[Swift 3.0 - Released on September 13, 2016]https://github.com/apple/swift-evolution/blob/master/releases/swift-3_0.md
还有@卓同学 的 Swift 3 必看系列
还有几个不错的总结
总结
总的说来这次迁移没有想象中的那么痛苦,虽然提案的改动很大,但是得益于 Xcode 8 的迁移工具,这次迁移花费时间不多,当然也有可能和我的代码量有关系~
在迁移完之后,再看代码,会发现 Swift 更加的优雅了,至少相比于 2 来说好了很多,至于好在哪里?你自己写写不就知道了咯。
最后,终于可以把 Xocde 7 卸载,再也不用担心两个一起开无脑闪退了!!!
最后对于明年的 Swift 4 只想说 快来吧~分分钟把你解决!
其实适配之路才刚刚开始,因为 Xcode 8 自动转的代码并没有很好的 Swift 3 化。目前只是说在 Swift 3 可以编译通过了而已~
更多
工作之余,写了点笔记,如果需要可以在我的 GitHub 看
Swift 3 新特性和迁移详解的更多相关文章
- h5新特性 File API详解
之前一直觉得h5的新特性就是一些新标签呢,直到想研究一下图片上传预览的原理,才发现还是有好多新的api的,只是不兼容ie低版本,挺可惜的, File API在表单中文件输入字段基础上,又添加了一些直接 ...
- IOS6 新特性之UIActivityViewController详解
新的IOS6增加了一些新特性.因为应用需要,所以在国庆的几天里.研究了一下IOS6的说明文档,然后大概地总结了一下UIActivityViewController的用法与大家分享. 首先 从实际效果入 ...
- [C++11新特性] 智能指针详解
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极为困难的.有时我们会忘记释放内存产生内存泄漏,有时提前释放了内存,再使用指针去引用内存就会报错. 为了更容易(同时也更安全)地使用动态内存, ...
- Android新特性Instant Run详解
关于 Instant Run Android Studio 2.0 中引入的 Instant Run 是 Run 和 Debug 命令的行为,可以大幅缩短应用更新的时间.尽管首次构建可能需要花费较长的 ...
- java8 array、list操作 汇【3】)(-Java8新特性之Collectors 详解
//编写一个定制的收集器 public static class MultisetCollector<T> implements Collector<T, Multiset<T ...
- Spring Boot 2.3 新特性优雅停机详解
什么是优雅停机 先来一段简单的代码,如下: @RestController public class DemoController { @GetMapping("/demo") p ...
- Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结
Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结 1. defer关键字1 2. try!形式存在的“不失败”机制3 3. Guard 4 4. swift的新语 ...
- Flex布局新旧混合写法详解(兼容微信)
原文链接:https://www.usblog.cc/blog/post/justzhl/Flex布局新旧混合写法详解(兼容微信) flex是个非常好用的属性,如果说有什么可以完全代替 float 和 ...
- Hadoop 新 MapReduce 框架 Yarn 详解
Hadoop 新 MapReduce 框架 Yarn 详解: http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-yarn/ Ap ...
随机推荐
- sql 里面 join in 的差别,join的用法
1. join 有 left join,right join,inner join 这三种,对两个表做了笛卡尔积,然后再对结果集进行选取操作,选取满足条件的部分为结果. JOIN(内联接): 如果表中 ...
- [ASE][Daily Scrum]11.19
Sprint2已经开始了~今天晚上有课所以今天的plan比较少~ View Shilin Liu 能够看见其他玩家发射出来的子弹 能够看见其他玩家的子弹消失 Client Jiafan ...
- Lzlib 1.5 正式发布,C 语言压缩算法库
Lzlib 1.5 正式发布,该版本移除了对废弃版本 0 文件的解压支持:修复了 struct LZ_Encoder 和 LZ_compress_sync_flush 相关的 bug. Lzlib 压 ...
- Dynamic CRM 2013学习笔记(九)CrmFetchKit.js介绍:Fetchxml、多表联合查询, 批量更新
CrmFetchKit.js是一个跨浏览器的一个类库,允许通过JavaScript来执行fetch xml的查询,还可以实现批量更新,分页查询等.目前已支持Chrome 25, Firefox 19 ...
- 跟我一起学WCF(13)——WCF系列总结
引言 WCF是微软为了实现SOA的框架,它是对微乳之前多种分布式技术的继承和扩展,这些技术包括Enterprise Service..NET Remoting.XML Web Service.MSMQ ...
- mysql 去除空格
update nm_user set nickname=TRIM(Replace(Replace(Replace(nickname,'\t',''),'\n',''),'\r',''))
- ViEmuVS2013-3.2.1 破解
VS升级到2013后,作为一个Vimer,自然需要更新最新的ViEmu插件,因为现在离了Vim,写代码已经寸步难行了. ViEmu 3.2.1的破解其实和Viemu 3.0.13的破解方法一样.安装前 ...
- Installing SCM-Manager
With SCM-Manager, people can share and manage Git, Mercurial and Subversion repositories over http e ...
- C# 两行代码实现 延迟加载的单例模式(线程安全)
关键代码第4,5行. 很简单的原理不解释:readonly + Lazy(.Net 4.0 + 的新特性) public class LazySingleton { //Lazy singleton ...
- paip.proxool连接池 :Attempt to refer to a unregistered pool by its alias 'xx'
paip.proxool连接池 :Attempt to refer to a unregistered pool by its alias 'xx' 作者Attilax 艾龙, EMAIL:146 ...