Swift 3 遷移工做總結

寫在前面

Swift 3.0 正式版發佈了差很少快一個月了,斷斷續續的把手上和 Swift 相關的遷移到了Swift 3.0。因此寫點小總結。git

背景

代碼量(4萬行)

首先,我是今年年初纔開始入手 Swift 的。加上 Swift 的 ABI 和 API 一直不穩定,因此沒有在項目中大範圍的使用,因此此次遷移的代碼量很少,大概在4萬行左右。github

遷移時間(一天左右)

遷移時間上的話,大概是花了1天左右。兩個混編項目,一個 Swift 爲主的項目。期中 Swift 爲主的項目 花了大概大半天時間,兩個混編代碼量差很少,可是一個花了小半天,還有一個差很少只花了半個小時(緣由先留個懸念~)。json

準備

在開發最初開發選擇 Swift 的時候的不少決策也讓我此次少了不少工做量。swift

界面用 xib 而不用純代碼api

陰差陽錯的,和 Swift 相關的大部分界面都是用xib 畫的。而這個 xib 在此次遷移中獲得了很大的優點,xib 和 SB 的代碼不適配 Swift 3。想當初要是使用代碼寫的 UI 的話,此次遷移改動估計會多不少吧。閉包

關於第三方庫的選擇:

對於一個項目來講,三方庫彷佛成了一道必選菜,可是如何去選擇這道菜呢?
對於三方庫,當初的選擇是,能用 OC 就儘可能用 OC。 畢竟能夠OC 能夠無縫銜接到 Swift,並且還相對穩定。
在選擇 Swift 相關的三方庫時,我儘可能值選擇使用者比較多的庫,例如Alamofire、Snap、Kingfisher、Fabric 等,由於使用者比較多,開發者會更願意去維護,而不至於跳票。因此不會存在如今許多小夥伴面臨的問題,想遷移,可是有些庫沒有更新。至少對於我來講,當我想遷移的時候,全部和 Swift 相關的三方庫都已經遷移到了 3.0 了。app

得益於上面兩點,在遷移過程當中少了很多工做量。🙈dom

知識儲備升級

先了解了一下Swift 2 到 Swift 3 的變更,及變更的緣由。(看完心中一萬頭草泥馬飛過,可是實際上是愈來愈好了)
Swift官博:https://swift.org/
swift-evolution:https://github.com/apple/swift-evolution/blob/master/releases/swift-3_0.md
Swift 3 新特性一覽:https://realm.io/cn/news/appbuilders-daniel-steinberg-whats-new-swift-3/
而後把語法文檔快速的重溫了一遍。
Swift Programming Language:https://developer.apple.com/swift/
中文版:http://wiki.jikexueyuan.com/project/swift/函數

遷移中的問題

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 = [<span class="hljs-link_label">String:AnyObect</span>]()
json["key1"] = 1 
json["key2"] = "2" 
 
// to Swift 3 Step 1
 var json = [<span class="hljs-link_label">String:AnyObect</span>]()
json["key1"] = 1 as AnyObject?
json["key2"] = "2" as AnyObject?
 
// to Swift 3 Step 2
 var json = [<span class="hljs-link_label">String:Any</span>]()
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 <NSObject>
@optional
 
- (void)animationDidStart:(CAAnimation *)anim;

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag; 
@end

由於寬度時間比較長,其餘的暫時想不到了。未完待續吧…

其餘

還有許多微妙的變化讓你彷佛看不懂這個語言了,因此建議在適配以前看一下下面的文章。
Swift 3 新特性一覽:https://realm.io/cn/news/appbuilders-daniel-steinberg-whats-new-swift-3/
[Swift 3.0 – Released on September 13, 2016]https://github.com/apple/swift-evolution/blob/master/releases/swift-3_0.md
還有@卓同窗 的 Swift 3 必看系列:http://www.jianshu.com/notebooks/6709594/latest
還有幾個不錯的總結
Swift 3 by 顧 鵬:http://tech.glowing.com/cn/swift3/
適配 Swift 3 的一點小經驗和坑 by 圖拉鼎:https://zhuanlan.zhihu.com/p/22584349

總結

總的說來此次遷移沒有想象中的那麼痛苦,雖然提案的改動很大,可是得益於 Xcode 8 的遷移工具,此次遷移花費時間很少,固然也有可能和個人代碼量有關係~
在遷移完以後,再看代碼,會發現 Swift 更加的優雅了,至少相比於 2 來講好了不少,至於好在哪裏?你本身寫寫不就知道了咯。
最後,終於能夠把 Xocde 7 卸載,不再用擔憂兩個一塊兒開無腦閃退了!!!
最後對於明年的 Swift 4 只想說 快來吧~分分鐘把你解決!
其實適配之路纔剛剛開始,由於 Xcode 8 自動轉的代碼並無很好的 Swift 3 化。目前只是說在 Swift 3 能夠編譯經過了而已~

本文轉載至來源:來源:Damonwong(@王浙劍)    連接:http://www.jianshu.com/p/f4761952b8c2

相關文章
相關標籤/搜索