公司准備讓整個項目打包成SDK,經過大量查閱打包SDK的博客,和自己的實踐,我把打包過程,中間遇到的各種問題,踩過的坑簡單的總結一下,讓看到的道友少踩些坑。
一、創建一個workspace
可以在桌面新建個testSDK文件夾,在這個文件夾里創建個WorkSpace。如圖:
二、創建SDK
1.打開workspace,創建一個project,如圖:
2.選擇Cocoa Touch Framework,如圖:
3.創建framework,把framework添加到workspace里。如圖:
三、創建SDKDemo
1.打開TestSDK.xcworkspace文件,創建project ,選擇Single View Application。如圖:
2.紅框里的都選擇TestSDK.xcworkspace。
這樣就把SDK和demo都創建好了,這樣創建SDK加demo可以方便調試,如果sdk中有問題,可以直接在SDK中斷點調試。創建后的效果如圖:
3.修改build settings 配置參數。如圖:
更改參數,在Architectures下增加armv7s,並選中。將Build Active Architecture only設置為NO
四、添加你的項目代碼到SDK中
如果你的項目用到了Xib,圖片,mp3,storyboard等,那么你就要添加一個bundle資源包,把這些資源添加到資源包里。
五、創建bundle資源包。
1.在target中點擊右下角的+號,選擇macOS,找到Framework&Library,選擇Bundle。如圖:
2.修改配置文件:
- "Base SDK" 設置為 "IOS"
- "Build Active Architecture Only" 設置為 "YES"
- "Debug Information Format" 設置為 "DWARF with dSYM File"
- "Skip Install" 設置為 "NO"
- "Strip Debug Symbols During Copy" 中"Release"模式設置為 "YES"
- "IOS Deployment Target" 設置為 "IOS 9.0"(具體根據自己的項目,設置系統版本)
- "COMBINE_HIDPI_IMAGES" 設置為 "NO"

4.選擇bundle,command + B編譯,如圖:
編譯之后,SDK工程下會多個bundle的文件夾,你可以把圖片,MP3,plist文件放到該文件夾里,如圖:
5.調用bundle資源包里的資源。
//調用自定義View的Xib
+(MyView *)instancePubView
{
NSArray * nibView = [[NSBundle mainBundle] loadNibNamed:@"testBL.bundle/MyView" owner:nil options:nil];
return [nibView objectAtIndex:0];
}
//調用視圖控制器的Xib
-(instancetype)init{
NSBundle * bundle = [NSBundle bundleWithPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"testBL.bundle"]];
self = [super initWithNibName:@"LoginViewController" bundle:bundle];
return self;
}
//調用圖片
UIImage *image = [UIImage imageNamed:@"home_banner_icon.png" inBundle:[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"testBL" ofType:@"bundle"]] compatibleWithTraitCollection:nil];
[self.BGimageView setImage:image];
//storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"testStoryboard" bundle:[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"testBL" ofType:@"bundle"]]];
//mp3
NSString *path = [[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"testBL" ofType:@"bundle"]] pathForResource:@"test" ofType:@"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: path];
//plist
NSString *filePath = [[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"testBL" ofType:@"bundle"]] pathForResource: @"test" ofType: @"plist"];
NSDictionary *plistDic = [NSDictionary dictionaryWithContentsOfFile:filePath];
需要用的資源,只要能從資源包里調出來就可以。
六、設置要公開的頭文件
1.設置Headers,將要公開的頭文件拖到Public下,要隱藏的放到Private或Project下,隱藏的頭文件不能被引用。如圖:
然后需要在TestSDK.h(必須是公開的,否則無法引用)中將所有要公開的.h引入引入頭文件
七、創建一個Aggregare(可以直接編譯SDK打包framework,也可用Aggregare這個打包)
1.創建Aggregate
點擊Add Target 后,如圖:
2.嵌入腳本,選中剛剛創建的Aggregare,然后選中右側的Build Phases,點擊左邊的+號,選擇New Run Phases。如圖:
3.下面把這段腳本復制進去(格式不要錯,格式錯編譯不通過)
# Sets the target folders and the final framework product.
# 如果工程名稱和Framework的Target名稱不一樣的話,要自定義FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}
# Install dir will be the final output to the framework.
# The following line create it in the root
folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_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}"
如圖:
4.最后編譯,command + B,編譯通過在finder中可以找到framework,把framework添加到你的demo中。
八、關聯framework,運行demo
1.導入頭文件,(解決警告:在TestSDK.h文件中添加公開的頭文件,如#import <TestSDK/LoginViewController.h>
,就可以消除警告。)
2.運行 demo
可能會遇到的問題:
1.整個項目打包成SDK不需要APPDelegate文件的,這里面的邏輯怎么辦?
在SDK Target里面是沒有compile Source 不需要APPDelegate文件,所以對於原工程APPDelegate的處理需要注意是否需要遷移進來。可以創建了一個私有的全局Manager類作為一個樞紐,里面放進了一些供全局調用的API和常量。也可以把之前項目的邏輯寫到demo的APPDelegate里。
2.SDK中第三方庫,拓展不能識別?
把第三方庫打到SDK中,在demo中運行SDK,當調用到部分第三方庫的時候不能識別第三方庫里的方法。我這邊是把所依賴的第三方庫在demo中再添加一邊。拓展也是一樣。這樣sdk中添加了一遍,demo中又添加了一遍,感覺有點不合理,SDK中不添加又會報錯(但不影響編譯,編譯成功照樣可以用),但是報錯就是很不爽,這樣你添加第三方庫的時候把add to target中testSDK選項去掉就行了,如下圖,這樣打包第三方就不會打2遍了,又不會報錯。當然一定會有更好的解決辦法,只是我沒找到。
3.自己打包的SDK,Could not build module 'testSDK錯誤。
原因是沒有把對外部公開的類中,在.h引用到的類,放到pulbic里面。當時報這個錯的時候我只導入了#import <TestSDK/TestSDK.h>文件,后來我把需要公開的頭文件都放到public里,然后用地方導入需要用的頭文件,就好了。
有錯誤的地方歡迎指正!