iOS-SDK開發(fā)經(jīng)驗(yàn)分享

本文目標(biāo):掌握封裝SDK的全部技巧及跳坑指南

本文目標(biāo):掌握封裝及開發(fā)SDK的全部技巧

文章比較長(zhǎng)蛔垢,建議分模塊閱讀

內(nèi)容提要:不同場(chǎng)景下如何封裝及開發(fā)SDK

  • .a靜態(tài)庫(kù)創(chuàng)建
  • 直接創(chuàng)建Framework庫(kù)
  • 在已有工程中創(chuàng)建
  • 創(chuàng)建Framework工程進(jìn)行封裝
  • 創(chuàng)建Bundle資源庫(kù)文件
  • 含界面SDK如何進(jìn)行依賴開發(fā)
  • 使用腳本創(chuàng)建Framework庫(kù),解決合并的煩惱
  • Swift 如何創(chuàng)建Framework庫(kù)

知識(shí)準(zhǔn)備

  • 終端命令
真機(jī)和模擬器上的庫(kù)文件合并 
Framework庫(kù)合并的是Framework內(nèi)包含的二進(jìn)制文件码邻,合并后替換庫(kù)中的文件,沒有.a后綴
lipo -create xxx.a(真機(jī)) xxx.a(模擬器) -output 新名字.a
查看SDK支持的架構(gòu)
lipo -info XXX.a  輸出: i386 armv7 x86_64 arm64

arm7: 在最老的支持iOS7的設(shè)備上使用
arm7s: 在iPhone5和5C上使用
arm64: 運(yùn)行于iPhone5S的64位 ARM 處理器 上
i386: 32位模擬器上使用
x86_64: 64為模擬器上使用
注意: 高位兼容地位(32位兼容16位),arm7版本可以在arm7s上運(yùn)行
需要在對(duì)應(yīng)架構(gòu)設(shè)備上運(yùn)行件缸,才能生成對(duì)應(yīng)架構(gòu)的包

  • category的處理

category是項(xiàng)目開發(fā)中經(jīng)常用到的洋闽,把category打包成靜態(tài)庫(kù)是沒有問題的溺忧,但是在使用這個(gè)靜態(tài)庫(kù)時(shí),
調(diào)用category中的方法時(shí)會(huì)發(fā)生找不到該方法的運(yùn)行時(shí)錯(cuò)誤(selector not recognized)敏弃,
解決的辦法是在使用靜態(tài)庫(kù)的工程中配置other linker flags的值為 -ObjC -all_load

  • 對(duì)圖片資源和UI界面xib或nib文件的處理

.a和.framework兩種靜態(tài)庫(kù)冰垄,通常都是把需要用的到圖片或者xib文件存放在一個(gè)bundle文件中,而該bundle文件的名字和.a或.framework的名字相同权她。
.a文件中無法存放圖片或xib文件虹茶,很容易理解,但是.framework從本質(zhì)上說也是一個(gè)bundle文件隅要,為什么不把圖片或者xib文件直接放在.framework中而單獨(dú)再創(chuàng)建個(gè)bundle文件呢蝴罪?
那是因?yàn)閕OS系統(tǒng)不會(huì)去掃描.framework下的圖片等資源文件,也不會(huì)在項(xiàng)目中顯示步清,也就是說即使放在 .framework目錄下要门,系統(tǒng)根本就不會(huì)去掃描,因此也無法發(fā)現(xiàn)使用

  • Debug和Release

Debug和Release廓啊,在我看來主要是針對(duì)其面向的目標(biāo)不同的而進(jìn)行區(qū)分的欢搜。
Debug通常稱為調(diào)試版本,通過一系列編譯選項(xiàng)的配合谴轮,編譯的結(jié)果通常包含調(diào)試信息炒瘟,而且不做任何優(yōu)化,以為開發(fā)人員提供強(qiáng)大的應(yīng)用程序調(diào)試能力第步。
Release通常稱為發(fā)布版本疮装,是為用戶使用的,一般客戶不允許在發(fā)布版本上進(jìn)行調(diào)試粘都。所以不保存調(diào)試信息廓推,同時(shí),它往往進(jìn)行了各種優(yōu)化翩隧,以期達(dá)到代碼最小和速度最優(yōu)樊展。為用戶的使用提供便利

開發(fā)指南

網(wǎng)上找了一個(gè)動(dòng)畫工程,作為我們開刀的對(duì)象
下載原始工程
如果你有耐性堆生,可以和我一起走完整個(gè)流程专缠。當(dāng)然每個(gè)模塊都是獨(dú)立的,你可以進(jìn)行針對(duì)性的閱讀

一顽频、.a靜態(tài)庫(kù)創(chuàng)建

  • 創(chuàng)建靜態(tài)庫(kù)工程 >> 刪除自動(dòng)創(chuàng)建的.m文件 >> 清空頭文件里的信息 >> 導(dǎo)入你要封裝的系統(tǒng)庫(kù)文件
創(chuàng)建靜態(tài)庫(kù)工程 libLoader(名字你高興就好)
刪除自動(dòng)創(chuàng)建的.m文件藤肢,清空頭文件里的信息
導(dǎo)入你要封裝的系統(tǒng)庫(kù)文件
  • 點(diǎn)擊目標(biāo)工程 >> Build Phases >> Editor >> add build Phases(是否公開頭文件選項(xiàng)) >> 設(shè)置公開訪問的頭文件(或在Target Membership中直接設(shè)置)

    目標(biāo)工程 > Build Phases > 點(diǎn)擊左側(cè)加號(hào) > add build Phases(是否公開頭文件選項(xiàng)) > 設(shè)置公開訪問的頭文件(或在Target Membership中直接設(shè)置)
添加頭文件選項(xiàng)
設(shè)置私有和暴露頭文件
設(shè)置私有和暴露頭文件
選擇sdk支持的系統(tǒng)版本
  • 參數(shù)設(shè)置
    • Build Settings >> Dead Code Stripping設(shè)置為NO
    • Build Settings >> Strip Debug Symbol During Copy 全部設(shè)置為NO
    • Build Settings >> Strip Style設(shè)置為Non-Global Symbols
    • Build Settings >> Base SDK >> Latest iOS(iOS 選擇最新的)
Dead Code Stripping設(shè)置為NO
Strip Debug Symbol During Copy 全部設(shè)置為NO
Strip Style設(shè)置為Non-Global Symbols
Base SDK >> Latest iOS(iOS 選擇最新的)
  • 在設(shè)備 和 模擬器 下分別按下command + B進(jìn)行編譯 >> 查看Product目錄 >> Show in Finder 查看編譯成功的靜態(tài)庫(kù)
  • debug模式下運(yùn)行生成 Debug-iphoneos 和 Debug-iphonesimulator兩個(gè)文件夾
  • release模式下運(yùn)行生成 Release-iphoneos 和 Release-iphonesimulator文件夾
切換編譯模式
分別查看.a庫(kù)文件
  • 合并Debug模式下的真機(jī)和模擬器下的靜態(tài)庫(kù)文件
使用終端進(jìn)行合并
cd 文件保存目錄
lipo -create 模擬器.a(路徑) 真機(jī).a(路徑) -output 重命名.a
查看架構(gòu)模式
lipo -info XXX.a  查看是否滿足運(yùn)行要求
  • 使用.a庫(kù)文件
    創(chuàng)建文件夾libAdvanced用于保存靜態(tài)庫(kù)信息 >> 替換剛剛合并的.a文件 >> 添加用到的圖片等資源文件 >> 導(dǎo)入工程驗(yàn)證
靜態(tài)庫(kù)完成
  • 創(chuàng)建新工程驗(yàn)證
  • 如果架構(gòu)報(bào)錯(cuò) Build Settings >> BuildActiveArchitecture Only Debug改為NO

二饮潦、直接創(chuàng)建Framework庫(kù)

<p id="jump"></p>

Framework是資源的集合望门,將靜態(tài)庫(kù)和其頭文件包含到一個(gè)結(jié)構(gòu)中,讓Xcode可以方便地把它納入到你的項(xiàng)目中。本質(zhì)也是一個(gè)bundle文件

  • 在已有工程中創(chuàng)建
    • 創(chuàng)建Framework
      點(diǎn)擊目標(biāo)工程 >> 點(diǎn)擊下面左下角加號(hào) >> 創(chuàng)建


      創(chuàng)建Framework
    • 參數(shù)配置
      點(diǎn)擊目標(biāo)工程 >> 選擇你創(chuàng)建的Framework >> 點(diǎn)擊工程設(shè)置 >> 做出如下修改

      Build Settings >> Dead Code Stripping >> 設(shè)置為NO

      Build Settings >> Strip Debug Symbol During Copy >> 全部設(shè)置為NO

      Build Settings >> Strip Style >> 設(shè)置為Non-Global Symbols

      Build Settings >> Base SDK >> Latest iOS(iOS 選擇最新的)

      Build Settings >>  Link With Standard Libraries >> 設(shè)置為 NO

      Build Settings >>  Mach-O Type >> Static Library

      對(duì)于Mach-O Type有兩種情況:(1)選擇 Static Library 打出來的是靜態(tài)庫(kù);(2)選擇 Relocatable Object File 打出來是動(dòng)態(tài)庫(kù)笤虫。
其他參數(shù)修改類似
  • 選擇framework支持的系統(tǒng)版本

  • 將需要打包的文件拖入到Framework中


    將需要打包的文件拖入到Framework中
  • 設(shè)置需要公開的文件


    設(shè)置暴露頭文件
  • 選擇運(yùn)行模式(debug 或 Release)分別在真機(jī)和模擬器下common + B 編譯生成對(duì)應(yīng)的Framework庫(kù)

  • 合并二進(jìn)制文件并替換

cd 到保存文件目錄下
lipo -create xxx/Debug-iphoneos/LibLoaderFramework.framework/LibLoaderFramework xxx/Debug-iphonesimulator/LibLoaderFramework.framework/LibLoaderFramework -output LibLoaderFramework
lipo -info LibLoaderFramework
輸出
Architectures in the fat file: LibLoaderFramework are: i386 arm64 
然后替換二進(jìn)制文件
image.png
  • 刪除Framework


    image.png
  • 如果沒有用到info.plist文件可以刪除烤宙,避免在工程中發(fā)生沖突
  • 驗(yàn)證
    導(dǎo)入完整Framework到工程箭昵,移除打包前的代碼愈污,對(duì)庫(kù)進(jìn)行驗(yàn)證
  • 建立Framework工程進(jìn)行創(chuàng)建
    • 使用xcode直接創(chuàng)建Framework工程

    • 把需要編譯的文件導(dǎo)入到工程中

    • 設(shè)置需要公開的頭文件


      image.png
    • 選擇Framework支持的系統(tǒng)版本

    • 配置參數(shù)

 參數(shù)配置基本都一樣
點(diǎn)擊目標(biāo)工程 >> 選擇你創(chuàng)建的Framework >> 點(diǎn)擊工程設(shè)置 >> 做出如下修改
  Build Settings >> Dead Code Stripping >> 設(shè)置為NO
  Build Settings >> Strip Debug Symbol During Copy >> 全部設(shè)置為NO
  Build Settings >> Strip Style >> 設(shè)置為Non-Global Symbols
  Build Settings >> Base SDK >> Latest iOS(iOS 選擇最新的)
  Build Settings >>  Link With Standard Libraries >> 設(shè)置為 NO
  Build Settings >>  Mach-O Type >> Static Library
  對(duì)于Mach-O Type有兩種情況:(1)選擇 Static Library 打出來的是靜態(tài)庫(kù);(2)選擇 Relocatable Object File 打出來是動(dòng)態(tài)庫(kù)。
-  選擇Debug(或Release)模式分別在模擬器和真機(jī)上 command + B 編譯

- 合并真機(jī)和模擬器下編譯的二進(jìn)制文件
cd到你想要保存合并后文件的目錄下
lipo -create xxx.framework/xxx ooo.framework/ooo -output ooo涨缚。
查看文件支持的架構(gòu)
lipo -info LibLoaderFramework
將合并成功的二進(jìn)制文件替換為framework中的二進(jìn)制文件轧粟,如果沒有用到info.plist文件,可以刪除脓魏,避免在工程中發(fā)生沖突
  • 創(chuàng)建新的工程兰吟,導(dǎo)入Framework進(jìn)行驗(yàn)證
如果工程無法聯(lián)想出Framework頭文件,導(dǎo)入路徑形式如下:
#import <LibLoaderFramework/PublicHeader.h>

三茂翔、創(chuàng)建Bundle資源庫(kù)文件

  • 創(chuàng)建Bundle工程


    創(chuàng)建Bundle工程
  • 配置幾個(gè)編譯設(shè)置

因?yàn)槟阏趧?chuàng)建一個(gè)在iOS上使用的bundle混蔼,這與默認(rèn)的OS X不同。
 Build Settings >> Base SDK >> Latest iOS (iOS 10.2選擇最新)
 Build Settings >> Product Name >> ${TARGET_NAME}替換為你的工程名XXXX(直接寫工程名就好)
################注意事項(xiàng)######################
默認(rèn)情況下珊燎,有兩種resolutions(分辨率)的圖片可以產(chǎn)生一些有趣的現(xiàn)象惭嚣。
例如,當(dāng)你導(dǎo)入一個(gè)retina@2x版本的圖片時(shí)悔政,普通版的和Retina版的將會(huì)合并成一個(gè)多resolution的TIFF(標(biāo)簽圖像文件格式晚吞,Tagged Image File Format)。
Build Settings > COMBINE_HIDPI_IMAGES設(shè)置為NO
  • 如何添加資源文件

    • 直接拖入
    • 選擇圖片或其他資源文件 > Target Membership > 選擇bundle目標(biāo)
  • 編譯工程并查看


    編譯工程并查看
  • Bundle文件使用時(shí)需要真實(shí)路徑

    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"LoaderBundle" withExtension:@"bundle"]];
    NSString *resourceStr = [bundle pathForResource:@"IMG_0017" ofType:@"JPG"];
    我們可以創(chuàng)建NSBundle分類避免重復(fù)書寫    
  • 創(chuàng)建工程驗(yàn)證

四谋国、含界面SDK如何進(jìn)行依賴開發(fā)

在無法看到真實(shí)效果的情況下為iOS開發(fā)一個(gè)UI控件庫(kù)是極其困難的,所以我們需要掌握依賴開發(fā)的知識(shí)

  • 創(chuàng)建Framework工程
  • 參數(shù)設(shè)置:參考如上第二章節(jié)
  • 創(chuàng)建驗(yàn)證工程
  • 關(guān)閉Framework工程
  • 添加Framework工程的xxxx.xcodeproj到驗(yàn)證工程并連接到靜態(tài)庫(kù)如圖操作:若未找到庫(kù)槽地,對(duì)庫(kù)進(jìn)行編譯
    添加Framework工程的xxxx.xcodeproj到驗(yàn)證工程并連接到靜態(tài)庫(kù)
  • 導(dǎo)入庫(kù)的公開頭文件,對(duì)驗(yàn)證工程進(jìn)行編譯
如果工程無法聯(lián)想出Framework頭文件烹卒,導(dǎo)入路徑形式如下:
#import <LibLoaderFramework/PublicHeader.h>

像這樣使用嵌套工程的好處是你可以對(duì)庫(kù)本身做出修改闷盔,而不用離開示例工程弯洗,即使你同時(shí)改變兩個(gè)地方的代碼也一樣旅急。每次你編譯工程,你都要檢查是否將頭文件的public/project關(guān)系設(shè)置正確牡整。如果實(shí)例工程中缺失了任何需要的頭文件藐吮,它都不能被編譯。

五逃贝、使用腳本創(chuàng)建Framework庫(kù)

  • 創(chuàng)建.a的靜態(tài)庫(kù)工程
    (創(chuàng)建方式與參數(shù)配置參照第一節(jié)不再贅述)
  • 使用腳本創(chuàng)建Framework目錄結(jié)構(gòu),此時(shí)不包含二進(jìn)制文件
  • 添加 New Run Script Phases
  • 雙擊面板標(biāo)題欄Run Script谣辞,重命名為Build Framework。
    • 這個(gè)面板允許你在構(gòu)建時(shí)運(yùn)行一個(gè)Bash腳本
    • 你希望讓腳本在build的過程中何時(shí)執(zhí)行沐扳,就把這個(gè)面板拖動(dòng)到列表中相對(duì)應(yīng)的那一位置泥从。
    • 對(duì)于該framework工程來說,腳本最后執(zhí)行沪摄,因此你可以讓它保留在默認(rèn)的位置即可躯嫉。


      使用腳本創(chuàng)建Framework目錄結(jié)構(gòu)
#set –e確保腳本的任何地方執(zhí)行失敗纱烘,則整個(gè)腳本都執(zhí)行失敗。
set -e

#導(dǎo)出framework路徑
export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"

# 創(chuàng)建當(dāng)前版本真實(shí)頭文件夾
mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"

# 創(chuàng)建引用路徑
/bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"

/bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"

/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \
"${FRAMEWORK_LOCN}/${PRODUCT_NAME}"

# 拷貝公共頭文件到framework中
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \ 
"${FRAMEWORK_LOCN}/Versions/A/Headers"

#######################簡(jiǎn)化目錄也可用使用如下腳本#######################

#set –e確保腳本的任何地方執(zhí)行失敗祈餐,則整個(gè)腳本都執(zhí)行失敗擂啥。
set -e

#導(dǎo)出的文件路徑
export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"

# 創(chuàng)建真是文件路徑
mkdir -p "${FRAMEWORK_LOCN}/Headers"

# 拷貝公共頭文件到framework中
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \
"${FRAMEWORK_LOCN}/Headers"
這個(gè)腳本做了如下三個(gè)操作:
1.創(chuàng)建了libLoader.framework/Versions/A/Headers目錄
2.創(chuàng)建了一個(gè)framework所需要的三個(gè)連接符號(hào)([symbolic links](http://en.wikipedia.org/wiki/Symbolic_link))

當(dāng)前版本文件夾
Versions/Current => A
頭文件夾
Headers => Versions/Current/Headers
二進(jìn)制文件
libLoader => Versions/Current/libLoader

3.將公共頭文件從你之前定義的公共頭文件路徑拷貝到Versions/A/Headers目錄下,-a參數(shù)確保修飾次數(shù)作為拷貝的一部分不會(huì)改變帆阳,防止不必要的重新編譯哺壶。
構(gòu)建成功后的Framework目錄
  • 多架構(gòu)(Multi-Architecture)編譯
    解決Framework或.a庫(kù)合并的煩惱,此處用的是.a工程蜒谤,使用Framework工程類似
  • iOS app需要在許多不同的CPU架構(gòu)下運(yùn)行:
 arm7: 在最老的支持iOS7的設(shè)備上使用
 arm7s: 在iPhone5和5C上使用 
 arm64: 運(yùn)行于iPhone5S的64位 ARM 處理器 上
 i386: 32位模擬器上使用
 x86_64: 64為模擬器上使用

每個(gè)CPU架構(gòu)都需要不同的二進(jìn)制數(shù)據(jù)山宾,當(dāng)你編譯一個(gè)應(yīng)用時(shí),無論你目前正在使用那種架構(gòu)鳍徽,Xcode都會(huì)正確地依照對(duì)應(yīng)的架構(gòu)編譯塌碌。例如,如果你想跑在虛擬機(jī)上旬盯,Xcode只會(huì)編譯i386版本(或者是64位機(jī)的x86_64版本)台妆。
這意味著編譯會(huì)盡可能快地進(jìn)行,當(dāng)你歸檔一款app或者構(gòu)建app的發(fā)布版本(release mode)時(shí)胖翰,Xcode會(huì)構(gòu)建上述三個(gè)用于真機(jī)的ARM架構(gòu)接剩。因此這樣app就可以跑在所有設(shè)備上了。不過萨咳,其他的編譯架構(gòu)又如何呢懊缺?讓我們一起往下走

  • 創(chuàng)建 Aggregate 集合
    點(diǎn)擊目標(biāo)工程 > 添加新目標(biāo) > Cross-Platform > Aggregate > next > 命名為Framework


    命名為Framework

為什么使用集合(Aggregate)目標(biāo)來創(chuàng)建一個(gè)framework呢?為什么這么不直接培他?因?yàn)镺S X對(duì)庫(kù)的支持更好一些鹃两,事實(shí)上,Xcode直接為每一個(gè)OS X工程提供一個(gè)Cocoa Framework編譯目標(biāo)舀凛】“猓基于此,你將使用集合編譯目標(biāo)猛遍,作為Bash腳本的連接串來創(chuàng)建神奇的framework目錄結(jié)構(gòu)馋记。
你是不是開始覺得這個(gè)方法有些懵逼了?

  • 添加依賴庫(kù)
    為了確保每當(dāng)這個(gè)新的framework目標(biāo)被創(chuàng)建時(shí)懊烤,靜態(tài)鏈接庫(kù)都會(huì)被編譯梯醒,你需要往靜態(tài)庫(kù)目標(biāo)中添加依賴(Dependency)。在庫(kù)工程中選擇Framework目標(biāo)腌紧,在Build Phases中添加一個(gè)依賴茸习。展開Target Dependencies面板,添加


    添加依賴庫(kù)
  • 添加多平臺(tái)編譯腳本
    這個(gè)目標(biāo)的主要編譯部分是多平臺(tái)編譯壁肋,你將使用一個(gè)腳本來做到這一點(diǎn)号胚。和你之前做的一樣
    選擇Framework目標(biāo) >> Build Phases >> 左側(cè) “+” 按鈕 >> New Run Script Phases >> 命名MultiPlatform Build
    ![MultiPlatform Build


  • 寫入編譯framewo編譯腳本

    #set –e確保腳本的任何地方執(zhí)行失敗代箭,則整個(gè)腳本都執(zhí)行失敗。
    set -e

    #標(biāo)示 如果已經(jīng)插入腳本 退出
    if [ -n "$IYQ_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then
    exit 0
    fi
    export IYQ_MULTIPLATFORM_BUILD_IN_PROGRESS=1

    # 自定義變量
    IYQ_FRAMEWORK_NAME=${PROJECT_NAME}
    IYQ_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"
    IYQ_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.framework"

    #構(gòu)建靜態(tài)庫(kù) 傳參 "${1}"
    function build_static_library {
    # 重新構(gòu)建庫(kù)
        xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \
        -target "${TARGET_NAME}" \
        -configuration "${CONFIGURATION}" \
        -sdk "${1}" \
        ONLY_ACTIVE_ARCH=NO \
        BUILD_DIR="${BUILD_DIR}" \
        OBJROOT="${OBJROOT}" \
        BUILD_ROOT="${BUILD_ROOT}" \
        SYMROOT="${SYMROOT}" $ACTION
    }

    #合并
    function make_fat_library {

        xcrun lipo -create "${1}" "${2}" -output "${3}"
    }

    # 1 正則判斷 真機(jī)還是模擬器 (iphoneos/iphonesimulator)
    if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then
    IYQ_SDK_PLATFORM=${BASH_REMATCH[1]}
    else
    echo "Could not find platform name from SDK_NAME: $SDK_NAME"
    exit 1
    fi

    # 2 SDK版本
    if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then
    IYQ_SDK_VERSION=${BASH_REMATCH[1]}
    else
    echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
    exit 1
    fi

    # 3 其他平臺(tái)判斷 如果 則 否則
    if [ "$IYQ_SDK_PLATFORM" == "iphoneos" ]; then
    IYQ_OTHER_PLATFORM=iphonesimulator
    else
    IYQ_OTHER_PLATFORM=iphoneos
    fi

    # 4 其他平臺(tái)路徑
    if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$IYQ_SDK_PLATFORM$ ]]; then
    IYQ_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${IYQ_OTHER_PLATFORM}"
    else
    echo "Could not find other platform build directory."
    exit 1
    fi

    #調(diào)用上面構(gòu)建函數(shù) 如果當(dāng)前運(yùn)行的是真機(jī)則構(gòu)建模擬器
    build_static_library "${IYQ_OTHER_PLATFORM}${IYQ_SDK_VERSION}"

    # 如果你現(xiàn)在正在為模擬器編譯涕刚,那么Xcode會(huì)默認(rèn)只在該系統(tǒng)對(duì)應(yīng)的結(jié)構(gòu)下編譯嗡综,例如i386 或 x86_64。為了在這兩個(gè)結(jié)構(gòu)下都進(jìn)行編譯杜漠,這里調(diào)用了build_static_library极景,基于iphonesimulator SDK重新編譯,確保這兩個(gè)結(jié)構(gòu)都進(jìn)行了編譯驾茴。
    if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then
    build_static_library "${SDK_NAME}"
    fi

    # 合并庫(kù)
    make_fat_library "${BUILT_PRODUCTS_DIR}/${IYQ_INPUT_STATIC_LIB}" \
    "${IYQ_OTHER_BUILT_PRODUCTS_DIR}/${IYQ_INPUT_STATIC_LIB}" \
    "${IYQ_FRAMEWORK_LOCATION}/${IYQ_FRAMEWORK_NAME}"

    # 確保文件存在 相當(dāng)于-dpR,保持文件的連接(d),保持原文件的屬性(p)并作遞歸處理(R)
    cp -a "${IYQ_FRAMEWORK_LOCATION}/${IYQ_FRAMEWORK_NAME}" \
    "${IYQ_OTHER_BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.framework/${IYQ_FRAMEWORK_NAME}"

    # 拷貝到指定目錄下
    ditto "${IYQ_FRAMEWORK_LOCATION}" "${SRCROOT}/BuildFramework/${IYQ_FRAMEWORK_NAME}.framework"
  • 在工程目錄下的BuildFramework文件下查看盼樟,并導(dǎo)入工程驗(yàn)證
    #import <libLoader/LoaderProgressView.h>

    BuildFramework在工程目標(biāo)下

  • SDK存在圖片,xib等資源文件的情況

  • 添加bundle目標(biāo)工程

  • bundle創(chuàng)建詳細(xì)操作參考第三節(jié)內(nèi)容

  • bundle目標(biāo)工程進(jìn)行編譯

  • 添加bundle資源庫(kù)依賴


    添加bundle資源庫(kù)依賴
  • 如果想把你的編譯包c(diǎn)opy到指定位置锈至,在腳本后面加入如下代碼

  # 拷貝bundle到指定目錄下
  ditto "${BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.bundle" \
  "${SRCROOT}/BuildFramework/${IYQ_FRAMEWORK_NAME}.bundle"

六晨缴、swift 工程如何創(chuàng)建Framework庫(kù)

  • swift支持靜態(tài)庫(kù)嗎?

  • iOS 8已經(jīng)開放了動(dòng)態(tài)庫(kù)的權(quán)限峡捡。

  • Swift 不在支持靜態(tài)庫(kù)击碗,這也就間接放棄了 iOS 7。

  • 項(xiàng)目中如果使用了自制的動(dòng)態(tài)庫(kù)们拙,能否上傳到AppStore?

  • 創(chuàng)建的動(dòng)態(tài)庫(kù)需要在 General >> Embedded Binaries 中添加才能使用

  • 蘋果把這種 Framework 稱為 Embedded Framework稍途。

  • 我們創(chuàng)建的這個(gè)動(dòng)態(tài)庫(kù)其實(shí)也不能給其他程序使用,只能是在我們的 App Extension 和 APP 之間共用砚婆。所有這種情況對(duì) AppStore 上架沒有影響械拍,可以正常發(fā)布。

  • 創(chuàng)建swift語(yǔ)言的Framework項(xiàng)目

  • 對(duì)外公開的 方法和類 需要添加 public 前綴

    對(duì)外公開的方法需要添加 `public` 前綴

    注意:如果還允許 **override **和繼承的話装盯,可以使用 **open **關(guān)鍵字坷虑。(關(guān)于訪問控制的詳細(xì)說明,可以參考我之前的這篇文章:Swift - 訪問控制(fileprivate埂奈,private迄损,internal,public挥转,open)

  • 分別在真機(jī)和模擬器上編譯
    為客戶提供使用的正式包請(qǐng)選擇release模式下編譯

  • 合并Framework二進(jìn)制文件

終端命令
cd 到Products目錄
真機(jī)和模擬器上的庫(kù)文件合并 
lipo -create xx/aa.framework/aa oo/aa.framework/aa -output aa
查看SDK支持的架構(gòu)
lipo -info LibLoaderFramework
  • 合并Mudules目錄下的內(nèi)容
  • 最后Framework的目錄結(jié)果


    image.png
  • 導(dǎo)入工程進(jìn)行驗(yàn)證
    因?yàn)槭莿?dòng)態(tài)庫(kù)海蔽,此處也需要導(dǎo)入,否則工程會(huì)崩潰
    image.png

    獲取全部源碼
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绑谣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拗引,更是在濱河造成了極大的恐慌借宵,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矾削,死亡現(xiàn)場(chǎng)離奇詭異壤玫,居然都是意外死亡豁护,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門欲间,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楚里,“玉大人,你說我怎么就攤上這事猎贴“喽校” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵她渴,是天一觀的道長(zhǎng)达址。 經(jīng)常有香客問我,道長(zhǎng)趁耗,這世上最難降的妖魔是什么沉唠? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮苛败,結(jié)果婚禮上满葛,老公的妹妹穿的比我還像新娘。我一直安慰自己罢屈,他們只是感情好纱扭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著儡遮,像睡著了一般乳蛾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鄙币,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天肃叶,我揣著相機(jī)與錄音,去河邊找鬼十嘿。 笑死因惭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绩衷。 我是一名探鬼主播蹦魔,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼咳燕!你這毒婦竟也來了勿决?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤招盲,失蹤者是張志新(化名)和其女友劉穎低缩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體曹货,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咆繁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年讳推,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玩般。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡银觅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出坏为,到底是詐尸還是另有隱情究驴,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布久脯,位于F島的核電站纳胧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏帘撰。R本人自食惡果不足惜跑慕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望摧找。 院中可真熱鬧核行,春花似錦、人聲如沸蹬耘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)综苔。三九已至惩系,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間如筛,已是汗流浹背堡牡。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杨刨,地道東北人晤柄。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像妖胀,于是被迫代替她去往敵國(guó)和親芥颈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容