公司准备让整个项目打包成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里,然后用地方导入需要用的头文件,就好了。
有错误的地方欢迎指正!