1. 程式人生 > >Swift專案中製作framework的方法和遇到的一些坑

Swift專案中製作framework的方法和遇到的一些坑

關於Swift整合framework的方法也查了很多資料,但大同小異,主要有兩種 1.利用cocoaTouch Framework建立如圖 進入xcode之後,裡面就是製作framework的介面和正常的專案一樣,不過不能執行(ps:這裡只是一個SDK並不是一個工程),只能編譯,編譯過之後就是就可以拿到framework的包,包的位置在products這個目錄下如圖
這裡解釋一下,圖中products目錄下就是我拿到的framework,右邊有程式碼的檔案是TestVC這個控制器類的測試程式碼,XRFramework02是隨工程建立之後產生的,Helloworld(繼承自NSObject)、TestVC、TestVC02這三個檔案是我建立的測試檔案,後面兩個繼承自UIViewController
注:補充一下swift的訪問控制的關鍵字
fileprivate :如名字一樣,只有這個檔案才能訪問. private: 只能在作用域訪問. interal: 預設,在整個模組可以訪問. public: 在模組裡面是可以繼承或者重寫,在模組外可以訪問,但不可以重寫和繼承. open:在所有模組都可以訪問,重寫和繼承. open> public > interal > fileprivate > private framework這裡簡單解釋一下,這裡會有執行環境不同分為Debug和Release,在兩種環境下都有模擬器測試和真機測試,根據自身情況可以選擇不同執行環境和測試環境,編譯就是Command+B,編譯完成就可以在Products目錄下找到framework包,從find中找到包,拖入自己的專案,在需要使用framework的檔案中匯入包名

上圖是另外一個測試專案,上面匯入包,下面就可以呼叫framework的程式碼,因為我在TestVC 類的程式碼是利用Alamofire呼叫的天氣介面(網上找的),程式碼直接在TestVC 類viewDidLoad新增的,所以進入TestVC 類就會執行被封裝進framework的程式碼,有不明白的地方請看文中的圖片。 前面說的framework是直接編譯之後 ,然後去framework所在資料夾中拖出來,拖到專案中的,因此可能會有執行環境和測試環境問題,其實這方面的問題也簡單:在什麼執行環境和測試環境中做的framework,就在什麼環境下呼叫framework,一般也不會有什麼問題。 通用版的framework自作:

注: 引入動態庫的時候,需要在工程配置嵌入動態庫,不然的話會報錯
644971-20161213110419714-1368172846.png 如果工程是oc工程的話,還需要在build Setting裡面配置一個選項為YES,否則也是執行報錯 644971-20161213110438464-905838743.png 合併模擬器版framework和真機版framework 分別用真機和模擬器build,右鍵選擇開啟framework的目錄,會發現有兩個release版本的framework. 644971-20161213110538636-1831625074.png 使用 lipo 命令合併兩個版本的framework. lipo -create ./Release-iphonesimulator/myFramework.framework/myFramework ./Release-iphoneos/myFramework.framework/myFramework -output ./myFramework 通用版本framwork: 通用版本的framework即將Debug/Release模式下編譯生成的framework(有兩種模擬器和真機環境下的應用場景),通用版本即是將Debug/Release模式下生成的framework合併成一個新的檔案,然後將新生成的檔案貼到Debug/Release的framework中,現在再拿這個新的framework就是通用版本的framwork。 使用指令碼自動化生成和合並framework.首先新增新的target.
644971-20161213110718526-371092549.png
644971-20161213110723104-1696528295.png 8.在紅框裡面輸入一段指令碼,然後選擇這個target進行build即可生成.
644971-20161213110742761-1009831627.png 指令碼程式碼: FMK_NAME=myFrameworkINSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.frameworkWRK_DIR=buildDEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.frameworkSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.frameworkxcodebuild -configuration "Release" -target"${FMK_NAME}" -sdk iphoneos clean buildxcodebuild -configuration"Release" -target"${FMK_NAME}" -sdk iphonesimulator clean buildif [ -d"${INSTALL_DIR}" ]thenrm -rf"${INSTALL_DIR}"fimkdir -p"${INSTALL_DIR}"cp -R"${DEVICE_DIR}/""${INSTALL_DIR}/"cp -R"${SIMULATOR_DIR}/""${INSTALL_DIR}/"# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.lipo -create"${DEVICE_DIR}/${FMK_NAME}""${SIMULATOR_DIR}/${FMK_NAME}" -output"${INSTALL_DIR}/${FMK_NAME}"rm -r"${WRK_DIR}"open “${INSTALL_DIR}" 在SDK開發的工程中如果單獨建立Cocoa Touch Framework的專案做framework的話,無法確定開發需要整合的功能,是否正常,有時候需要一邊做功能另外可以執行測試功能,這裡也補充一下這種情況的做法,新建專案 -> 選擇target -> 選擇Add Target ->Cocoa Touch Framework,流程就是這樣的流程,下面上圖說明:


在上圖中第二步箭頭位置點選選擇Add Target,然後再出來的視窗中選擇Cocoa Touch Framework,建立玩Cocoa Touch Framework,剩下的做法就和上面的做法一樣了。 最近發現一個新的問題,當framework中封裝的檔案包含xib/storyBoard 時,直接呼叫viewcontroller是不能呈現xib/storyboard上面的內容的,因此想要呈現xib/storyboard的內容可以採取以下的辦法 這裡分兩種情況第一種針對viewcontroller的xib檔案具體做法如下所示: let bundle = Bundle.init(for: TestViewController.self) let testVC = TestViewController.init(nibName: "TestViewController", bundle: bundle) self.present(testVC, animated: true, completion: nil) 這裡的TestViewController是測試viewcontroller,帶有xib,如果viewcontroller不帶有 xib 關聯檔案,在呼叫framework的時候,就可以直接push或者present呼叫,可以正常顯示。 第二種情況是framework帶有storyboard,然後呼叫framework的storyboard中的viewcontroller,這裡介紹使用方法如下: let path = Bundle.main.path(forResource: "XRFramework05", ofType: "framework") print("檢視路徑:\(path!)") let bundle = Bundle.init(path: path!) let storyBoard = UIStoryboard.init(name: "TestMyStoryboard", bundle: bundle) let loginVC = storyBoard.instantiateViewController(withIdentifier: "TestViewController02") self.present(loginVC, animated: true, completion: nil) 這裡有一點需要注意,呼叫framework的viewcontroller的時候,需要在專案的Build Phase ->copy bundle resources中新增framework,這裡還有一個點需要注意就是上面的let loginVC = storyBoard.instantiateViewController(withIdentifier: "TestViewController02")這一行程式碼中的identifier是storyboard的xib檔案的storyboard ID沒有新增需要自己新增上,這樣才能正常呼叫,否則會報錯。 另外再補充一條,我這裡用的Swift 3.2,這裡使用範圍也是在Swift 3.2的專案,理論說情況類似,但是在Swift 4.0 中會拋棄一些方法,可能會出現問題,這裡暫時先不說。