將工程從 CocoaPods 遷移到到 SwiftPM

[遷移背景故事]:
國慶前把之前一個已經發(fā)布的工程改了下配置重新上架纳像,結果編譯死活通過不了窖张,報的錯主要是Segmentation fault: 11Command CompileSwift falied with a nonzero exit code :,項目初次遇到這個問題時是在第一次打包時遍愿,當時查閱資料說是 Xcode 的 Bug 清除緩存重新編譯就順利上線了存淫。

這次網上各種方法試了個遍都沒效果,好在是個小工程不復雜沼填,項目在做模塊化的時候使用 CocoaPods 配合 framework 拆分了基礎模塊和公共業(yè)務。最后迫不得已將分拆的基礎模塊又導入回主工程下括授,再次編譯坞笙,發(fā)現(xiàn)是 MJRefresh 給組件附加的 header 和 footer 在調用時沒有加上可選標識的問號,修復后編譯通過荚虚。

推測是因為 MJRefresh 由 Objective-C 編寫而成薛夜,之前的版本可能是舊版本 Xcode 對 OC 類型進行 可選檢查 沒有深入到子模塊,最新版本的 Xcode 新增了對 OC 對象更深入的檢查卻沒有對子模塊響應的提示版述,以至于我們打開 Swift 報錯檢查等操作并沒有具體信息梯澜。

好巧不巧,這幾天鼓搗了下 SwiftPM 后渴析,這個為上架被迫臨時還原的項目正好可以拿來試試 SwiftPM 的成色如何晚伙。本文記錄了該工程從 CocoaPods 遷移到 SwiftPM 過程中遇到的問題以及解決辦法。

[閱讀難度:簡單]

以筆者的小工程為例俭茧,CocoaPods 導入的三方庫大約十來個咆疗,包含了Swift與OC兩種類型的庫,這些庫對 SwiftPM(Swift Package Mananger)的適配狀態(tài)也不盡相同母债。遷移的過程從最簡單的情況開始一個一個解決午磁。


Swift 類型的庫

Swift 類型的庫屬于最簡單的情況,直接用 SwiftPM 引入即可毡们,諸如 Alamofire迅皇、KingfisherSnapKit 等庫衙熔。對 Xcode 中如何使用SwiftPM 還不了解的同學可以參考官方文檔或者 上一篇文章


Objective-C 類型的庫

SwiftPM 本是專門針對 Swift 誕生的登颓,由于歷史原因,很多庫是由OC編寫而成青责,如何引入OC的包挺据?可以分為兩種情況:

1. 支持 SwiftPM 的庫

這一類跟Swift的庫一樣直接導入就可以了取具,這里可以借鑒 MBProgressHUD 庫的官方實現(xiàn),在其 Package.swift 文件中配置如下:

import PackageDescription

let package = Package(
    name: "MBProgressHUD",
    products: [
        .library(name: "MBProgressHUD", targets: ["MBProgressHUD"])
    ],
    targets: [
        .target(
            name: "MBProgressHUD",
            dependencies: [],
            path: ".",
            exclude: ["Demo"],
            sources: ["MBProgressHUD.h", "MBProgressHUD.m"],
            publicHeadersPath: "include"
        )
    ]
)

大體和 Swift 庫一致扁耐,特別注意 sources 這里暇检,庫的 OC 文件都列在了這里,publicHeadersPath 則是需要公開的頭文件目錄婉称,自定義OC庫想了解詳細設置可查看官方文檔或參考 MBProgressHUD 的實現(xiàn)块仆。

但這種方式有個問題,對于MBProgressHUD這樣個位數(shù)文件的OC庫實行起來倒是沒什么影響王暗,如果是 MJRefresh 這樣幾十個文件還附帶資源文件怎么辦悔据?可能這也是MJRefresh到目前為止依舊沒有適配SwiftPM的原因之一。(在最新的 Swift5.3 中已經支持導入資源文件俗壹,SE-0271

2. 未支持 SwiftPM 的 OC 庫

最直接的方法是自己創(chuàng)建一個 Swift Package 的中間庫科汗,自行配置Package.swift與各種文件。就像上面說的绷雏,這種方法耗費太多的時間头滔,隨著庫的發(fā)展,三方庫大改涎显,中間庫的配置就要大改坤检,想到這里腸胃一陣蠕動, Pass期吓。

那就曲線救國早歇,在 Swift 為主的工程中,引入的 OC 庫都比較少讨勤,且都是經得起時間考驗的精品庫箭跳,沒有適配 SwiftPM 的就更少了⌒螅可以將這類 OC 庫打包成 Framework 直接丟進項目中即可衅码。這里筆者借助了 CocoaPods 的一個插件 cocoapods-binary,因為CocoaPods在安裝三方庫時會將其所以來的庫一并安裝脊岳,省去不少麻煩逝段。具體過程如下:

1. 安裝 cocoapods-binary:

$ gem install cocoapods-binary

2. 新建個空工程。
3. 創(chuàng)建Pod文件(以MJRefresh為例):

source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '13.0'       // 這里改為指定系統(tǒng)版本
inhibit_all_warnings!
use_frameworks!             // 動態(tài)庫
plugin 'cocoapods-binary'    // 插件  
all_binary!                 // 插件應用于全部庫

abstract_target 'BASE_POD' do

    pod 'MJRefresh'

    target 'StaticLibDemo' do 
        project 'StaticLibDemo.xcodeproj'
        workspace 'StaticLibDemo.xcworkspace'
    end
end

4.在當前工程下調用 pod install 命令
**5.生成的庫在生成的 Pods 文件下割捅,路徑為: **

/Pod/_Prebuild/GeneratedFrameworks/

6.將其中生成的庫復制到我們的項目中(如:MJRefresh.framework奶躯,僅僅是framework,別的不要亿驾,否則發(fā)布報錯)

這里生成的庫會有 x86_32 架構嘹黔,在發(fā)布時會報 IPA progress fail,需要將此架構從庫中移除。

具體方法:

  1. 命令面板跳轉到framework: $ cd /XXX/XXXX/包名.framework
  2. 查看信息: $ lipo -info 包名儡蔓,這里會顯示出 i386郭蕉、x86_64
  3. 移除:
    $ lipo -remove i386 包名 -o 包名
    $ lipo -remove x86_64 包名 -o 包名
  4. 再次查看信息確認移除成功后即可將包導入工程。

7.因為我們生成的是動態(tài)庫喂江,所以別忘了在 General 中將導入的動態(tài)庫設置為“embed & sign”

至此召锈,我們就可以正常替換之前在 CocoaPods 引入的 MJRefresh 了,這只是權宜之計获询,有更好的辦法的小伙伴歡迎補充 [猛男微笑.gif]涨岁。


遇到的問題

用 SwiftPM 導入庫后,編譯報錯 not found 'xxxxx'

建議備份一下工程吉嚣,這類錯誤的原因不一定相同梢薪。

筆者解決方法:通過刪除 Build setting 下 Other Linking 的所有配置可編譯正常

RxSwift 的導入問題

因為工程以來的基礎模塊應用到了 RxSwift 所以基礎模塊的SwiftPackage依賴于RxSwift,然而這個庫目前(20201015)對SwiftPM的支持是有問題的(相關鏈接)尝哆。而這導致使用 RxSwift 給出的配置來配置項目時秉撇,Xcode無法識別,也無法在

按照官方方法配置子模塊的 Package.swift:

import PackageDescription

let package = Package(
    name: "RJSuger",
    platforms: [.iOS(.v13)],
    products: [
        .library(
            name: "RJSuger",
            targets: ["RJSuger"]),
        .library(
            name: "RJBaseWidgets",
            targets: ["RJBaseWidgets"]),
    ],
    dependencies: [
        .package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1")),
        .package(url: "https://github.com/ReactiveX/RxSwift.git", .exact("6.0.0-rc.1"))
    ],
    targets: [
        .target(
            name: "RJSuger",
            dependencies:[],
            path: "Sources/RJSuger"),
        .target(
            name: "RJBaseWidgets",
            dependencies: ["RJSuger","SnapKit","RxSwift", "RxCocoa"],
            path: "Sources/RJBaseWidgets"),
        .testTarget(
            name: "RJSugerTests",
            dependencies: ["RJSuger"]),
    ],
    swiftLanguageVersions: [.v5]
)

這樣的配置對于筆者的模塊较解,Xcode 識別不出來畜疾,報出來的錯誤指向了 最后添加的依賴項 RxCocoa,參考 RxSwift的文件結構是RxSwift下有 RxSwift印衔、RxCocoa、RxRelay等模塊姥敛,嘗試性的將對應的 Targets 依賴變更為:

//····
  dependencies: ["RJSuger","SnapKit",.product(name: "RxSwift", package: "RxSwift"),.product(name: "RxCocoa", package: "RxSwift")],
//···

編譯通過奸焙。


總結

從 2018 年推出 SwiftPM 到現(xiàn)在,SwiftPM 已經可以應付大部分庫管理的場景彤敛,對自定義模塊的支持也不錯与帆,不出問題的時候使用起來真是清爽自然。而當遇到問題時墨榄,網絡上資料可能很少玄糟,也可能直接就是三方庫或 SwiftPM 本身的問題不得不另尋他法。最最最重要的問題是加載庫的速度和機制袄秩,稍微大點的庫本身速度就慢阵翎,稍微變動下工程結構,SwiftPM 就莫名所有庫重新加載一次之剧,導致大量時間浪費在這上面郭卫,而SwiftPM 的 checkout 下來的庫對存在 DriveData/工程文件/SourcePackages/checkout下,對于老夫這種喜歡清理 DriveData 的人不得不備份一份在其抽風時替換背稼。

所以個人建議:SwiftPM 建議了解下贰军,實際應用到項目,膽子小的:

再等一年又何妨

Thanks for reading :)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蟹肘,一起剝皮案震驚了整個濱河市词疼,隨后出現(xiàn)的幾起案子俯树,更是在濱河造成了極大的恐慌,老刑警劉巖贰盗,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件许饿,死亡現(xiàn)場離奇詭異,居然都是意外死亡童太,警方通過查閱死者的電腦和手機米辐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來书释,“玉大人翘贮,你說我怎么就攤上這事”澹” “怎么了狸页?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扯再。 經常有香客問我芍耘,道長,這世上最難降的妖魔是什么熄阻? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任斋竞,我火速辦了婚禮,結果婚禮上秃殉,老公的妹妹穿的比我還像新娘坝初。我一直安慰自己,他們只是感情好钾军,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布鳄袍。 她就那樣靜靜地躺著,像睡著了一般吏恭。 火紅的嫁衣襯著肌膚如雪拗小。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天樱哼,我揣著相機與錄音哀九,去河邊找鬼。 笑死唇礁,一個胖子當著我的面吹牛勾栗,可吹牛的內容都是我干的。 我是一名探鬼主播盏筐,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼围俘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起界牡,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤簿寂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宿亡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體常遂,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年挽荠,在試婚紗的時候發(fā)現(xiàn)自己被綠了克胳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡圈匆,死狀恐怖漠另,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情跃赚,我是刑警寧澤笆搓,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站纬傲,受9級特大地震影響满败,放射性物質發(fā)生泄漏。R本人自食惡果不足惜叹括,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一算墨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汁雷,春花似錦米同、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽少孝。三九已至继低,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稍走,已是汗流浹背袁翁。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留婿脸,地道東北人粱胜。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像狐树,于是被迫代替她去往敵國和親焙压。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353