Swift 4遷移總結:喜憂參半,新的起點

此次Swift 3 到 4 的遷移代碼要改動的地方比較少,花了一個下午的時間就完成了遷移。Swift 把原來 4.0 的目標從 ABI 穩定改成了源碼兼容,這次代碼的兼容性作的確實很好,這個目標算是達到了。然而對於一個成熟的項目而言,單純語法上的兼容並非所有,此次的升級也帶來了一些新的變化。git

3.2 和 4.0

在 3.0 的時候 swift 也提供了 2.3 和 3.0 兩個版本,此次 4.0 也是提供了 3.2 版本。從我項目裏的代碼來看,從 3.0 到 3.2 要作的改動幾乎沒有,只是須要從新編譯一次。社區的反應來看兼容 3.2 也沒反饋出什麼大的改動。因此對於推遲跟進 4.0 的團隊來言會是一個很順滑的過分,能夠安心的切換到 Xcode 9。github

爲了讓你們在遷移過程當中更加順利,swift 的 framework 支持 3.2 和 4.0 版本混編。若是你有好幾個組件,能夠單獨爲某個組件升級到 4.0 。這樣大的團隊能夠不用一口氣全部的代碼都遷移到 4.0。
然而 3.2 和 4.0 的兼容並無看上去那麼美好。
編程

首先是cocoapods的問題,反正在目前pods的framework只能指定一個版本的swift。issue在這裏:Pods automatically compiling with Swift 4.0 in Xcode 9 beta 1 。pod默認會使用一個swift版本編譯所有,須要對不一樣的庫單獨指定swift版本。swift

遇到這個問題後,我把全部組件都遷移到了 4.0 ,app 由於有不少業務代碼,但願先遷到 3.2 ,這樣能夠儘早支持 Xcode 9,同事能夠儘早適配 iOS 11。然而。。。
網絡

Xcode 果真沒讓我失望啊,編譯的時候沒有錯誤提示只告訴你失敗了:
app

compiling as Swift 3.2, with 'xxx' build as Swift 4.0(this is supported but may expose additional compiler issues)性能

提示也很清奇,我翻譯一下:咱們雖然支持混編,可是也可能混出毛病,因此你仍是別混了。不過聽聞丁香園的項目目前是主 app 4.0,組件 3.2 混編是成功的。因此說呢,若是要混能夠碰碰運氣。優化

順便說下Xcode 9新的編譯系統,我這裏根本編譯不過(可能由於咱們混OC?),並且沒有任何錯誤提示。蘋果的軟件質量果真是獨領風騷,面向運氣編程。ui

社區跟進及時

因此實際上,你要否則就全不動,停在 3.2。一旦要遷移就須要所有遷移到 4.0 。this

好在此次由於語法改動小,我用到的大部分 Swift 庫都支持了 4.0。棄更的只有 DOFavoriteButton ,一個點讚的控件。跟進比較慢的有 RxGesture、EZSwiftExtensions,不過已經也有了 4.0 的分支,也有人提了 4.0 的 PR,估計過幾天應該也能合進去。只能說維護的人不夠積極。
下面把我用到的 pod 貼出來:

3.2 4.0
RxSwift/RxCocoa 4.0.0-beta.0
SnapKit 4.0.0
CryptoSwift 0.7.0 0.7.1
Alamofire 4.5.1 4.5.1兼容(5.0還未發佈)
ObjectMapper 2.2.9 3.0
SwiftyAttributes 3.2.0 4.0.0
Kingfisher 4.1.0 4.0
MonkeyKing 1.4.0

一般狀況下3.0是能夠直接在3.2下編譯的,因此「無」並不表示不能使用,指開發者沒有單獨聲明一個版本兼容3.2。

4.0 開始與 OC 正式分道揚鑣

爲了照顧原有的開發者,Swift 2.0 的時候要作到的目標是與 OC 儘可能兼容,除了幾個基礎的數據類型好比 Int、String 與OC不一樣外,其餘的 API 都和 OC 保持一致,徹底能夠用 OC 的習慣寫 Swift 。到 3.0 的時候Swift 體系開始獨自進化,開始有本身的命名規範。

到 4.0 的時候,Xcode 用 Swift 重寫了編譯器,雖然 New build system 目前還在 preview,也確實有不少問題,然而針對 Swift 的編譯優化又取得了不小的提高。我已經能感受到蘋果想要拋棄 OC 的意思,至少是很是明顯的嫌棄的意思。

從代碼層面來看,原先一個類只要是 NSObject 的子類,默認這個類的全部的屬性方法都會自動添加給 OC 調用的 bridge,在 4.0 裏這個功能被關閉了。這也是遷移 4.0 的一個比較大的工做量(對於和 OC 混編的項目)。什麼意思呢,之前咱們用 Swift 自定義了一個控件,原先在 OC 中引入 module 的頭文件後,能夠調用到這個控件公開的全部屬性、方法。可是遷移到 4.0 後,全部屬性、方法默認都是不能訪問到,須要到控件裏給要暴露給 OC 使用的屬性方法前加上 @objc 。

這個改動影響很是深遠。這等因而讓開發者二選一了。若是咱們用 Swift 寫一個組件,須要支持 OC 加上 @objc 標誌,編譯時就要生成給 OC 調用的聲明,這下降了一些些性能。可是不加的話 OC 又調用不到。更深的緣由是,在寫組件的時候咱們並不確切的知道業務方是用 OC 仍是 Swift 調用的。除非業務代碼全是 Swift。或者只能全盤作 OC 橋接,處處都是 @objc,若是上面調用的是 Swift,這些又白加了。

這裏還出現了另一個細節。若是咱們在 OC 裏給 UIView 聲明瞭一個屬性 size,在 Swift 裏也聲明瞭一個屬性 size。若是是在一個 framework 裏,會編譯失敗提示衝突了。然而若是這兩個寫在不一樣的 framework 裏,Xcode 不會提示。在 8 的時候,這個 size 的調用最後會走到 OC 的方法,可是在 9 的時候,在 Swift 代碼裏引入這個 OC framework,代碼就直接崩潰了,會不知道應該調用那個庫的 size。這顯然是編譯器的一個 bug,但這也側面反映了,OC 和 Swift 混編帶來的問題愈來愈多,兩個體系的區別會愈來愈大。

#總結
遷移到 4.0 的代價比以前要小的多, ABI 穩定很大可能在 5.0 到來。對於觀望 Swift 是否穩定的開發者而言是個好消息,相信 Swift 的接受程度會更高。Swift 一年一個版本的升級和 OC 的分野會愈來愈大,給混編帶來了不少的不肯定性,對於混編的項目有能力的仍是把一些代碼遷移到 Swift。

對於 Xcode 我有一個經驗再次和你們分享一下:Xcode 有兩個版本,一個不穩定的版本和一個更不穩定的版本。

歡迎在社交網絡上關注我:

相關文章
相關標籤/搜索