這次Swift 3 到 4 的遷移代碼要改動的地方比較少蟀瞧,花了一個(gè)下午的時(shí)間就完成了遷移。Swift 把原來 4.0 的目標(biāo)從 ABI 穩(wěn)定改為了源碼兼容,此次代碼的兼容性做的確實(shí)很好,這個(gè)目標(biāo)算是達(dá)到了。然而對于一個(gè)成熟的項(xiàng)目而言盟劫,單純語法上的兼容并不是全部,這次的升級也帶來了一些新的變化与纽。
3.2 和 4.0
在 3.0 的時(shí)候 swift 也提供了 2.3 和 3.0 兩個(gè)版本侣签,這次 4.0 也是提供了 3.2 版本塘装。從我項(xiàng)目里的代碼來看,從 3.0 到 3.2 要做的改動幾乎沒有影所,只是需要重新編譯一次蹦肴。社區(qū)的反應(yīng)來看兼容 3.2 也沒反饋出什么大的改動。所以對于推遲跟進(jìn) 4.0 的團(tuán)隊(duì)來言會是一個(gè)很順滑的過度猴娩,可以安心的切換到 Xcode 9阴幌。
為了讓大家在遷移過程中更加順利,swift 的 framework 支持 3.2 和 4.0 版本混編卷中。如果你有好幾個(gè)組件矛双,可以單獨(dú)為某個(gè)組件升級到 4.0 。這樣大的團(tuán)隊(duì)可以不用一口氣所有的代碼都遷移到 4.0蟆豫。
然而 3.2 和 4.0 的兼容并沒有看上去那么美好背零。
首先是cocoapods的問題,反正在目前pods的framework只能指定一個(gè)版本的swift无埃。issue在這里:Pods automatically compiling with Swift 4.0 in Xcode 9 beta 1 。pod默認(rèn)會使用一個(gè)swift版本編譯全部毛雇,需要對不同的庫單獨(dú)指定swift版本嫉称。
遇到這個(gè)問題后,我把所有組件都遷移到了 4.0 灵疮,app 因?yàn)橛泻芏鄻I(yè)務(wù)代碼织阅,希望先遷到 3.2 ,這樣可以盡早支持 Xcode 9震捣,同事可以盡早適配 iOS 11荔棉。然而。蒿赢。润樱。
Xcode 果然沒讓我失望啊,編譯的時(shí)候沒有錯(cuò)誤提示只告訴你失敗了:
compiling as Swift 3.2, with 'xxx' build as Swift 4.0(this is supported but may expose additional compiler issues)
提示也很清奇羡棵,我翻譯一下:我們雖然支持混編壹若,但是也可能混出毛病,所以你還是別混了皂冰。不過聽聞丁香園的項(xiàng)目目前是主 app 4.0店展,組件 3.2 混編是成功的。所以說呢秃流,如果要混可以碰碰運(yùn)氣赂蕴。
順便說下Xcode 9新的編譯系統(tǒng),我這里根本編譯不過(可能因?yàn)槲覀兓霴C舶胀?)概说,而且沒有任何錯(cuò)誤提示碧注。蘋果的軟件質(zhì)量果然是獨(dú)領(lǐng)風(fēng)騷,面向運(yùn)氣編程席怪。
社區(qū)跟進(jìn)及時(shí)
所以實(shí)際上应闯,你要不然就全不動,停在 3.2挂捻。一旦要遷移就需要全部遷移到 4.0 碉纺。
好在這次因?yàn)檎Z法改動小,我用到的大部分 Swift 庫都支持了 4.0刻撒。棄更的只有 DOFavoriteButton ,一個(gè)點(diǎn)贊的控件骨田。跟進(jìn)比較慢的有 RxGesture、EZSwiftExtensions声怔,不過已經(jīng)也有了 4.0 的分支态贤,也有人提了 4.0 的 PR,估計(jì)過幾天應(yīng)該也能合進(jìn)去醋火。只能說維護(hù)的人不夠積極悠汽。
下面把我用到的 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還未發(fā)布) |
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下編譯的,所以“無”并不表示不能使用芥驳,指開發(fā)者沒有單獨(dú)聲明一個(gè)版本兼容3.2柿冲。
4.0 開始與 OC 正式分道揚(yáng)鑣
為了照顧原有的開發(fā)者,Swift 2.0 的時(shí)候要做到的目標(biāo)是與 OC 盡量兼容兆旬,除了幾個(gè)基礎(chǔ)的數(shù)據(jù)類型比如 Int假抄、String 與OC不同外,其他的 API 都和 OC 保持一致丽猬,完全可以用 OC 的習(xí)慣寫 Swift 宿饱。到 3.0 的時(shí)候Swift 體系開始獨(dú)自進(jìn)化,開始有自己的命名規(guī)范脚祟。
到 4.0 的時(shí)候谬以,Xcode 用 Swift 重寫了編譯器,雖然 New build system 目前還在 preview由桌,也確實(shí)有很多問題蛉签,然而針對 Swift 的編譯優(yōu)化又取得了不小的提升。我已經(jīng)能感覺到蘋果想要拋棄 OC 的意思沥寥,至少是非常明顯的嫌棄的意思碍舍。
從代碼層面來看,原先一個(gè)類只要是 NSObject 的子類邑雅,默認(rèn)這個(gè)類的所有的屬性方法都會自動添加給 OC 調(diào)用的 bridge片橡,在 4.0 里這個(gè)功能被關(guān)閉了。這也是遷移 4.0 的一個(gè)比較大的工作量(對于和 OC 混編的項(xiàng)目)淮野。什么意思呢捧书,以前我們用 Swift 自定義了一個(gè)控件吹泡,原先在 OC 中引入 module 的頭文件后,可以調(diào)用到這個(gè)控件公開的所有屬性经瓷、方法爆哑。但是遷移到 4.0 后,所有屬性舆吮、方法默認(rèn)都是不能訪問到揭朝,需要到控件里給要暴露給 OC 使用的屬性方法前加上 @objc 。
這個(gè)改動影響非常深遠(yuǎn)色冀。這等于是讓開發(fā)者二選一了潭袱。如果我們用 Swift 寫一個(gè)組件,需要支持 OC 加上 @objc 標(biāo)志锋恬,編譯時(shí)就要生成給 OC 調(diào)用的聲明屯换,這降低了一些些性能。但是不加的話 OC 又調(diào)用不到与学。更深的原因是彤悔,在寫組件的時(shí)候我們并不確切的知道業(yè)務(wù)方是用 OC 還是 Swift 調(diào)用的。除非業(yè)務(wù)代碼全是 Swift索守≡我ぃ或者只能全盤做 OC 橋接,到處都是 @objc蕾盯,如果上面調(diào)用的是 Swift,這些又白加了蓝丙。
這里還出現(xiàn)了另外一個(gè)細(xì)節(jié)级遭。如果我們在 OC 里給 UIView 聲明了一個(gè)屬性 size,在 Swift 里也聲明了一個(gè)屬性 size渺尘。如果是在一個(gè) framework 里挫鸽,會編譯失敗提示沖突了。然而如果這兩個(gè)寫在不同的 framework 里鸥跟,Xcode 不會提示丢郊。在 8 的時(shí)候,這個(gè) size 的調(diào)用最后會走到 OC 的方法医咨,但是在 9 的時(shí)候枫匾,在 Swift 代碼里引入這個(gè) OC framework,代碼就直接崩潰了拟淮,會不知道應(yīng)該調(diào)用那個(gè)庫的 size干茉。這顯然是編譯器的一個(gè) bug,但這也側(cè)面反映了很泊,OC 和 Swift 混編帶來的問題越來越多角虫,兩個(gè)體系的區(qū)別會越來越大沾谓。
總結(jié)
遷移到 4.0 的代價(jià)比之前要小的多, ABI 穩(wěn)定很大可能在 5.0 到來戳鹅。對于觀望 Swift 是否穩(wěn)定的開發(fā)者而言是個(gè)好消息均驶,相信 Swift 的接受程度會更高。Swift 一年一個(gè)版本的升級和 OC 的分野會越來越大枫虏,給混編帶來了很多的不確定性妇穴,對于混編的項(xiàng)目有能力的還是把一些代碼遷移到 Swift。
對于 Xcode 我有一個(gè)經(jīng)驗(yàn)再次和大家分享一下:Xcode 有兩個(gè)版本模软,一個(gè)不穩(wěn)定的版本和一個(gè)更不穩(wěn)定的版本伟骨。
歡迎在社交網(wǎng)絡(luò)上關(guān)注我:
- 推特:@慶春路卓富貴
- 微博:@沒故事的卓同學(xué)