Swift 版本升級嘛,你們應該都很熟練了,菜單 -> Edit -> Convert -> To Current Swift Syntax...,而後巴拉巴拉一頓操做。emmmn,抱歉,編譯過了也不必定能正常使用。git
此次 Swift 3 到 Swift 4 的更新和以前的大版本更新相比,已經平滑了不少,相較以前的動輒幾百上千個 error,如今用 Xcode 進行 Convert 以後基本上只須要進行少許人工修正便可,不過仍然有一些點須要注意,本文將會對一些常見的坑或者注意點以及解決方法進行討論。github
本文以 EFCountingLabel 的 1.0.3 版本和 Xcode 9.0 爲例,主要關於原有的 Swift 3 的 CocoaPods 庫到 Swift 4 的升級,仍處於 Swift 2 階段的同窗可暫時忽略本文。swift
首先用 Xcode 打開工程,看一下當前工程設置的 Swift 版本,若是太低的話可能沒法直接 Convert,選中須要轉換的 target 搜索 swift_ver
便可,如圖所示:bash
這裏 EFCountingLabel 的 Swift 版本爲 3.2,若是是 2.x 的話須要本身想辦法先轉換成 Swift 3.x...函數
接下來,就是利用 Xcode 實現代碼轉換了,菜單 -> Edit -> Convert -> To Current Swift Syntax...,而後選中須要轉換的 target,點擊 Next
按鈕便可:post
而後會出現一個轉換模式選項,有 Minimize Inference(recommended)
和 Match Swift 3 Behavior
兩個選擇,蘋果推薦的是第一個選項:測試
蘋果官方文檔對這兩個選項的描述以下,大意是:若是選第一個選項,會僅在必要的時候爲方法或屬性添加 @objc
標誌,不過大部分工做須要用戶(也就是你)手動完成,好處是能減小最終生成的二進制文件的大小;若是選擇第二個選項,則會按 Swift 3 的方式給全部的地方直接添加 @objc
標誌(關於 @objc
標誌的介紹你們能夠參考 Swift 翻譯組的這篇文章),缺點就是不會對生成的二進制文件大小進行優化(也就是跟 Swift 3 同樣):優化
這裏咱們分幾種狀況:spa
Minimize Inference(recommended)
,檢查而且保存自動轉換結果便可,而後能夠直接跳到下一小節,請忽略下面這一大段;@objc
標誌或者對這一點二進制文件體積的縮減並非十分在乎的話,選 Match Swift 3 Behavior
,檢查而且保存自動轉換結果便可,而後能夠直接跳到下一小節,請忽略下面這一大段;Minimize Inference(recommended)
,保存更改,而後按下面的操做去作:1. 編譯工程;
2. 修正那些提示你須要添加 @objc 標誌的警告(請務必修正,否則即便編譯能過運行時也可能會出問題);
3. 修正 Xcode 提示的不須要添加 @objc 標誌的代碼,持續構建和測試你的代碼,直到沒有任何警告出現;
4. 打開工程設置;
5. 選中 target,搜索 `@objc` 找到 `Swift 3 @objc Inference` 選項,設爲 `Default`。
複製代碼
唔,以上這段大概是原文翻譯過來的了,官方文檔原文如圖所示:翻譯
須要注意的是,由於咱們這裏針對的並非完整的 iOS 項目,而是 CocoaPods 庫,若是你的 OC Demo 沒有調用庫中須要暴露的功能(或者乾脆沒有 OC Demo),辣麼編譯器可能徹底不會給你任何提示而是直接經過編譯了,直到你某一天在一個 OC 工程中引入這個庫纔會發現並不能調用到某些方法或獲取某些屬性。
因此其實麻煩之處在於,編譯器並不會給你任何提示,由於編譯器也不知道哪些類 / 屬性 / 方法須要暴露,哪些須要被優化掉,須要開發人員本身決定並手動添加對應的 @objc
標誌,總結起來的話有如下幾點:
#selector
的方式調用的話,能過編譯而且在運行時直接找不到對應方法而閃退,建議升完 Swift 4 檢查一下全部的 #selector 調用);Perform Changes
按鈕便可;Swift 3 @objc Inference
設置(若是有的話)改成 Default
,以前改過的話就不用改了;swift_ver
,能夠看到當前的 Swift Language Version
已是 Swift 4
了。剩下少許方法名變更之類的更新你們能夠根據提示自行修改,到這裏基本就完成了升級過程,不過先別急,接下來咱們看注意事項。
如下狀況必需要給對應的屬性或方法添加 @objc
標誌(固然,他們所在的類確定也須要添加 @objc
標誌),不論是經過 OC 仍是 Swift 調用:
@selector()
或 #selector()
方式調用的函數;這些有部分在官方文檔中也有說起:
Swift 的版本控制粒度在 framework 層面,也就是說同一個工程中不一樣的 framework 能夠是按不一樣版本的 Swift 進行編譯的,因此並不須要等待項目依賴的全部 Pods 庫都支持 Swift 4 後再更新,徹底能夠將已經升級 Swift 4 的庫先用起來。
Swift 3 @objc Inference
選項是幹啥的?在 Swift 4 以前,編譯器對 Objective-C 自動提供了一些 Swift 聲明。例如,編譯器會爲 NSObject 子類的全部方法建立 Objective-C 入口點,該機制稱爲 @objc 推斷(@objc Inference)。
在 Swift 4 中,這種自動的 @objc 推斷已被廢棄,由於生成全部這些 Objective-C 入口點有代價,會增大最終的二進制文件體積。當 Swift 3 @objc Inference
設置爲 On
時,它會按照 Swift 4 以前的模式運行,不進行優化,也就是隱式爲咱們編寫的全部 Swift 代碼提供 OC 入口。
可是,當設置爲 On
時 Xcode 會報一個警告,建議修復這個警告,並將設置切換到 Default
。新的 Swift 項目的默認爲「Default」。能夠理解爲該項設置爲 On
時和上文代碼轉換時選擇 Match Swift 3 Behavior
選項效果相似。
升級完請務必跑一遍總體測試流程,暗坑無數,以防萬一,祝你們線上穩定。
若有任何知識產權、版權問題或理論錯誤,還請指正。 https://juejin.im/post/5a32180551882554b83790ca 轉載請註明原做者及以上信息。