iOS SDK开发

有这样一个需求:开发一个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
iOS SDK开发_第1张图片
1
2、在SDK中导入MBProgressHUD库,并创建SDKDemoViewController
iOS SDK开发_第2张图片
代码目录

SDKDemoViewController中书写如下代码

3

配置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
iOS SDK开发_第3张图片
设置 Build Configuration

设置公开头文件
默认的公开头文件为SDKDemo.h,只需要设置SDKDemoViewController.h

iOS SDK开发_第4张图片
设置公开头文件

每设置一个公开头文件,都需要在 SDKDemo.h文件中按如下方式引入
iOS SDK开发_第5张图片
引头文件

3.创建bundle
  1. sdk 中xib,图片等一切资源都需要添加到Bundle中。
    点击File-New-Target-macOS-Bundle,取名为SDKDemoBundle

    iOS SDK开发_第6张图片
    添加bundle

  2. 按照下图,将xib添加到bundle中。后续的图片等资源都需要按种方式添加。


    iOS SDK开发_第7张图片
    4

    配置Bundle

  • TARGETS -SDKDemoBundle-BuildSettings-Base SDK 设置 iOS
  • Build Active Architecture Only 设置为NO
  • Enable Bitcode 设置为NO
  • 清除Installation Directory路径信息
  • Skip install设置为YES
  • COMBINE_HIDPI_IMAGES设置为NO
  • Edit scheme-Run-Build Configuration设置为Release
4.编译Bundle,并导入到SDK中

编译Bundle,Xcode按如下方式选择Target为SDKDemoBundle,command + B。编译后,在products目录下,会发现生成的Bundle

iOS SDK开发_第8张图片

sdk中以如下方式,引入刚编译的Bundle
iOS SDK开发_第9张图片
5

删除SDK里面的多余xib,bundle中已经存在该xib了
iOS SDK开发_第10张图片
6

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
    iOS SDK开发_第11张图片
    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

iOS SDK开发_第12张图片
7
  • 设置Edit scheme-Run-Build Configuration设置为Release
6.编译SDK

分别将sdk在模拟器(随便选一款模拟器)和Generic iOS Device下编译 (选择该target,command + B)。这会编译生成2个SDK,一个适用于模拟器,一个适用于真机。

SDK模拟器

Generic iOS Device

选择Target选为CommonDylib编译,这会将上面生成的2个SDK合成一个,编译完成后,会发现在项目根目录会生成Products文件夹,便是所制作的sdk

iOS SDK开发_第13张图片
生成SDK

7.创建测试工程,导入SDK、bundle和MBProgressHUD
iOS SDK开发_第14张图片
test工程

需要注意的是,

  • bundle在framework下,需要将其复制出来导入到工程中。
    iOS SDK开发_第15张图片
    bundle
    .

2019年3月21日说明:也可不用将bundle复制出来,就让它存在于framework中。此时,在SDK的代码中引入bundle,改成这种形式[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"Frameworks/SDKDemo.framework/SDKDemoBundle" withExtension:@"bundle"]],这个路径是固定的Frameworks/SDK名字.framework/Bundle名字。例如,我们将其定义为一个宏,#define SDKBoundle [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"Frameworks/SDKDemo.framework/SDKDemoBundle" withExtension:@"bundle"]],那么,在SDK中创建一个UIImage对象就可这样写[UIImage imageNamed:strFileName inBundle:SDKBoundle compatibleWithTraitCollection:nil];,亲测有效。


  • sdk的导入方式如下。动态库的导入方式均是这种方式。


    iOS SDK开发_第16张图片
    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支持的架构时 只有arm7arm64,没有arm7s。查询了百度地图等主流SDK后均没有对arm7s提供支持,具体原因未知。运行工程时,Xcode会打印一系列警告,不影响上架,具体原因未知。

下一篇:静态库开发


参考文章

  • iOS 使用动态库
  • 包含 Bundle 资源的 framework 的正确打包方式
  • SDK开发经验分享
  • 制作静态Framework
  • iOS静态库SDK制作

你可能感兴趣的:(iOS SDK开发)