有这样一个需求:开发一个SDK,SDK需要用到AFNetworking等常用第三方库,且主项目中也会用到同样的三方库。
一直以来开发iOS SDK的常用方式是使用静态库
开发,当SDK中需要用到类似AFNetWorking
且主项目中也会用到AFNetWorking
时,XCode会提示duplicate symbol
,且这个问题一直没有有效的处理方式。类似需求,查询网上资料,什么cocoapods
私有库,公有库,结果越扯越远。
其实,早在WWDC2014苹果在iOS上便开放了动态库。使用动态库便可以解决上面静态库所面临的问题。我公司采用动态库开发SDK已迭代多个版本,且已成功上架。本文以封装MBProgressHUD
为例,介绍SDK开发,脚本和bundle的使用。github地址 https://github.com/wutao23yzd/SDKDemo。
SDK动态库开发
1、创建动态库,取名为SDKDemo
![](https://img.haomeiwen.com/i7443959/1b6dbae41d12dee4.png)
2、在SDK中导入MBProgressHUD
库,并创建SDKDemoViewController
![](https://img.haomeiwen.com/i7443959/070a4a76cb6d32d3.png)
在SDKDemoViewController
中书写如下代码
![](https://img.haomeiwen.com/i7443959/d6f555a1fecbb164.jpg)
配置Xcode
- TARGETS -Build Settings - Build Active Architchture Only 设置为No
- TARGETS->Build Settings->Other Linker Flags,添加
-ObjC
- TARGETS->Build Settings->Enable Bitcode 设置为No
Edit scheme
-Run
-Build Configuration
设置为Release
![](https://img.haomeiwen.com/i7443959/a39278c9fa12857b.png)
设置公开头文件
默认的公开头文件为SDKDemo.h
,只需要设置SDKDemoViewController.h
![](https://img.haomeiwen.com/i7443959/0217ce2694d0d42f.png)
每设置一个公开头文件,都需要在
SDKDemo.h
文件中按如下方式引入![](https://img.haomeiwen.com/i7443959/ca3d1f81ea96f8fb.png)
3.创建bundle
-
sdk 中
xib
,图片等一切资源都需要添加到Bundle中。
点击File
-New
-Target
-macOS
-Bundle
,取名为SDKDemoBundle
。
添加bundle
-
按照下图,将xib添加到bundle中。后续的图片等资源都需要按种方式添加。
4
配置Bundle
- TARGETS -SDKDemoBundle-BuildSettings-Base SDK 设置
iOS
- Build Active Architecture Only 设置为
NO
- Enable Bitcode 设置为
NO
- 清除
Installation Directory
路径信息Skip install
设置为YESCOMBINE_HIDPI_IMAGES
设置为NOEdit scheme
-Run
-Build Configuration
设置为Release
4.编译Bundle,并导入到SDK中
编译Bundle,Xcode按如下方式选择Target为SDKDemoBundle,command + B
。编译后,在products
目录下,会发现生成的Bundle
![](https://img.haomeiwen.com/i7443959/242fbf6b74988bab.png)
sdk中以如下方式,引入刚编译的Bundle
![](https://img.haomeiwen.com/i7443959/2a3b8be35fb1a9c0.png)
删除SDK里面的多余xib,bundle中已经存在该xib了
![](https://img.haomeiwen.com/i7443959/513b8e33db9aed25.png)
在
SDKDemoViewController.m
中添加如下代码
- (instancetype)init {
self = [super initWithNibName:@"SDKDemoViewController" bundle:[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"SDKDemoBundle" withExtension:@"bundle"]]];
if (self) {
return self;
}
return self;
}
5.为SDK添加脚本
SDK以模拟器编译时,会生成对应模拟器架构的SDK( i386,x86_64);以
Generic iOS Device
编译时,会生成真机架构的SDK(arm7,arm64)。脚本的作用是将这两个sdk合成一个,使的同时适用于真机和模拟器。
-
File
-New
-Target
-Cross-platform
-Aggregate
,取名为CommonDylib
。
在其Target Dependencies
中`添加SDKDemo
6
- 点击下图中的 + 号,选择run script,添加如下脚本
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
#open "${DEVICE_DIR}"
#open "${SRCROOT}/Products"
fi
![](https://img.haomeiwen.com/i7443959/92cb7ecae061b3ec.png)
- 设置
Edit scheme
-Run
-Build Configuration
设置为Release
6.编译SDK
分别将sdk在模拟器(随便选一款模拟器)和Generic iOS Device
下编译 (选择该target,command + B
)。这会编译生成2个SDK,一个适用于模拟器,一个适用于真机。
![](https://img.haomeiwen.com/i7443959/af3ac25bbb633f91.png)
![](https://img.haomeiwen.com/i7443959/478d6edacf0adac0.png)
选择Target选为CommonDylib
编译,这会将上面生成的2个SDK合成一个,编译完成后,会发现在项目根目录会生成Products
文件夹,便是所制作的sdk
![](https://img.haomeiwen.com/i7443959/ac80289aa1069264.png)
7.创建测试工程,导入SDK、bundle和MBProgressHUD
库
![](https://img.haomeiwen.com/i7443959/a542955697117908.png)
需要注意的是,
- bundle在framework下,需要将其
复制
出来导入到工程中。
bundle .
-
sdk的导入方式如下。动态库的导入方式均是这种方式。
SDK导入
运行工程,查看效果
sdk.gif
可以看到虽然sdk和主项目中,含有相同的三方库,但并没有报错。
7.上架APPStore
采用动态库开发,上传appstore时需要将i386 x86_64两个平台删除后,才能正常提交。删除方式参考 《http://docs.easemob.com/im/300iosclientintegration/20iossdkimport 集成动态库上传AppStore》。
cd
到framework的当前目录下 利用lipo -info SDKDemo.framework/SDKDemo查看支持的架构。
- arm7: 在支持iOS7之前的设备上使用
- arm7s: 在iPhone5和iPhone5C上使用
- arm64: 在iPhone5S以上的64位ARM处理器上使用
- i386: 在32位模拟器上使用
- x86_64: 在64位模拟器上使用
// xx 代表framework的名字
lipo xx.framework/xx // 查看framework支持的架构
// 输出 armv7
lipo xx.framework/xx -thin armv7 -output xx_armv7
// 输出 arm64
lipo xx.framework/xx -thin arm64 -output xx_arm64
// 合并
lipo -create xx_armv7 xx_arm64 -output xx
// 移动覆盖
mv xx xx.framework/
删除后,查看sdk支持的架构时 只有arm7
和arm64
,没有arm7s
。查询了百度地图等主流SDK后均没有对arm7s提供支持,具体原因未知。运行工程时,Xcode会打印一系列警告,不影响上架,具体原因未知。
参考文章
网友评论