美文网首页大前端开发
iOS静态库开发基础

iOS静态库开发基础

作者: shaosolas | 来源:发表于2019-08-15 09:24 被阅读12次

一、为什么用库

1、为了方便共享源代码,在分享的同时又不愿意暴露源代码及具体实现

2、实现iOS程序组件化,可以把固定的业务模块化成库文件,方便多个工程使用,节省编译时间

3、开发第三方SDK的需要(企业级业务)

二、库的简介

2.1、什么是库?

库是一段编译好的二进制代码,附加上公开的头文件,代码就可以供其他开发者使用。在使用库的时候,编译时只需要链接就好。根据库的链接方式,分为静态库和动态库两类。

2.2、静态库与动态库的区别?

静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。

动态库:链接时不复制到可执行文件中,程序运行时由系统动态加载到内存,程序中只存储指向动态库的引用。系统只加载一次,多个程序共用,节约了内存。

针对iOS项目,可以以下面的方式来简单区分:

以==Embedded Binaries==方式导入为动态库;

以==Link Binary With Libraries== 方式导入为静态库。

2.3、iOS中静态库

.a和.framework。

主流的SDK开发方式,腾讯、百度等大厂的SDK主要采用静态开发方式。

静态库不能嵌套(见iOS中Framework Library嵌套使用),这样可以减少库与其他库之间的耦合。

但是在使用静态库的时候,需要导入所依赖的其他库文件,这样会比较麻烦。因此,当SDK需要引用其他SDK,且不希望将内部实现暴露给用户时,那么就会采用动态库形式,这种一般是系统级的库文件。

2.4、iOS中动态库

.dylib,.tbd和.framework,主要是系统组件。

若SDK和项目中用到相同的三方库(如:AFNetworking),在使用动态库时,工程和项目中可以存在2份AFNetworking,因此开发相对方便一些。而静态库只会存在一份,因此开发相对复杂,但是可以减少代码的冗余。

注意:

在导入自定制的动态库时,要在Embedded Binaries中导入,不然会报错:image not found。

2.5、framework为什么既是静态库又是动态库?

.framework本质上并不是一个库,它是苹果为了方便开发者提供了一种库的打包方式,Framework会将Mach-O文件、头文件和资源包全都包含进来,不需要你再手动整理,我们也可以通过Xcode来制作framework动态库使用。

系统的.framework是动态库形式。

开发者所创建的.framework大部分是静态库,因此需要拷贝到目标程序中。

所以说.framework既可以是静态库也可以是动态库,这取决于编译成的Mach-O(就是那个二进制文件)是以动态库还是静态库形式编译。

综上: .framework是iOS开发中库的一种打包形式,既可以是动态库也是静态库。

2.6、a与.framework有什么区别?

.a是一个纯二进制文件,.framework中除了有二进制文件外还有资源文件,一个比较简单的描述即.a + .h + sourceFile = .framework。

所以.a文件不能直接使用,需要添加对应的.h文件,而.framework文件可以直接供开发者使用。

2.7、静态库开发的注意事项:

1、无论是.a静态库还.framework静态库,需要的都是二进制文件+.h+其它资源文件的形式。不同的是,.a本身就是二进制文件,需要我们手动加上.h和其它资源文件,而.framework本身已经包含了.h和其它文件。

2、图片资源的处理:在.a和.framewok两种静态库文件,一般都是把图片资源拿出,相应放在一个.bundle、.bundle的名字可以和.a或.framework的名字相同。一种方式是:可直接创建一个文件夹,后缀名为.bundle,在显示包内容时,添加图片资源文件。另一种方式是:在Xcode的工程中添加bundle target,添加图片资源文件。

3、Category在实际开发项目中会经常用到的。将Category打包成静态库,不会有什么问题的。但是在应用该静态库的工程中,会遇到调用Category的方法,找不到该方法的运行时错误(Selector not recognized)。这是因为链接标志所造成的,需要在应用静态库的工程配置,在==Other linker flags==处,添加『-ObjC』。

4、如果一个静态库较为复杂,必须暴露的.h文件过多,可在静态库的内部创建一个专门的.h文件(一般这个.h文件的名字和静态库名相同),然后把所有需要暴露的.h文件集中到此.h文件,再把这个.h文件暴露即可。

三、静态SDK开发流程

3.1、静态SDK的创建和配置

1、创建空白Xcode Workspace

2、创建SDK工程

(1)创建SDK

在当前workspace中创建SDK工程,如图1所示,并将SDK工程与workspace关联,如图2所示。

图1.png
图2.png

配置SDK为静态库。

配置==Deployment Target==iOS 9.0

Mach-O Type ==Static Library==

Enable Bitcode ==No==

Edit Scheme - Run - Info - Build Configuration ==Release==

(2)创建Bundle

因为在静态库中,SDK中的图片资源及xib等,需要添加到对应的Bundle中。所以在步骤(1)中的工程添加『target』,如图3所示,并配置如下:

图3.png

Build Settings - Base SDK - ==iOS==

Deployment Target -9.0

Enable Bitcode ==NO==

清除Build settings - Installation Directory路径信息

COMBINE_HIDPI_IMAGES设置为==NO==

Edit Scheme - Run - Info - Build Configuration ==Release==

(3)配置生成脚本

在iOS开发中,模拟器运行平台为PC,架构为i386和x86_64等,而真机的架构为arm7和arm64等。所以,为了使SDK在模拟器及真机上都可运行,则需编译生成两个在不同平台的SDK,然后再用工具合二为一。

在SDK工程中,添加对应的Aggregate工程。

图4.png

在设置Build Phrase中设置Target Dependices关联SDK工程,另外为Run Script添加下列代码,如图5所示。

#  This is a modified script and it will ask the target to build separate libraries for simulator and device etc   
# On project folder it will be found under Generated-Frameworks folder  
# As per the documentations for XCode 10 Apple does not allow building FAT librares  
# Go ahead and check https://forums.developer.apple.com/thread/66978 and https://forums.developer.apple.com/thread/109583  
# Enjoy NicoX :)  

set -e  
# If we're already inside this script then die  
if [ -n "$MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then  
exit 0  
fi  
export MULTIPLATFORM_BUILD_IN_PROGRESS=1  

############################################  
# Options  
############################################  
REVEAL_ARCHIVE_IN_FINDER=true  
OUTPUT_DIR_NAME="Generated-Frameworks" 

FRAMEWORK_NAME="${PROJECT_NAME}"  

OUTPUT_DIR="${PROJECT_DIR}/${OUTPUT_DIR_NAME}/${FRAMEWORK_NAME}-${CONFIGURATION}-framework"  
SIMULATOR_LIBRARY_OUT_DIR="${OUTPUT_DIR}/Simulator/"  
GENERATED_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"  
SIMULATOR_FRAMEWORK_OUT_DIR="${GENERATED_LIBRARY_DIR}/Simulator"  
FRAMEWORK="${SIMULATOR_FRAMEWORK_OUT_DIR}/${FRAMEWORK_NAME}.framework"  

########################################################################  
# Build Frameworks  
########################################################################  
xcodebuild -scheme ${PROJECT_NAME} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator OBJROOT="${OBJROOT}/DependantBuilds"   

########################################################################  
# Create directory for general  
########################################################################  
rm -rf "${GENERATED_LIBRARY_DIR}"  
mkdir "${GENERATED_LIBRARY_DIR}"  
mkdir "${SIMULATOR_FRAMEWORK_OUT_DIR}"  
mkdir "${FRAMEWORK}"  

########################################################################  
# Copy files Framework  
########################################################################  
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"  

########################################################################  
# Make a binary for simulaotr ie. x86_64 ot i386 file system  
########################################################################  
# For Swift framework, Swiftmodule needs to be copied in the universal framework   
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then  
cp -f "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/"* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo  
fi  
cp -r "${SIMULATOR_LIBRARY_PATH}/." "${FRAMEWORK}"  

########################################################################  
# Copy simulator build library in output folder  
########################################################################  
rm -rf "$OUTPUT_DIR"  
mkdir -p "$OUTPUT_DIR"  
mkdir -p ${SIMULATOR_LIBRARY_OUT_DIR}  

cp -r "${FRAMEWORK}" "$SIMULATOR_LIBRARY_OUT_DIR"  
#########################################################################  

echo "Simulator Lib Path ---->" "${SIMULATOR_LIBRARY_PATH}" "<----"  

##########################################################################  
# Now lets build for device; shall we?  
##########################################################################  
DEVICE_LIBRARY_OUT_DIR="${OUTPUT_DIR}/Device/"  
DEVICE_FRAMEWORK_OUT_DIR="${GENERATED_LIBRARY_DIR}/Device"  
FRAMEWORK="${DEVICE_FRAMEWORK_OUT_DIR}/${FRAMEWORK_NAME}.framework"  

########################################################################  
# Build Device Frameworks  
########################################################################  
xcodebuild -scheme ${PROJECT_NAME} -sdk iphoneos ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos OBJROOT="${OBJROOT}/DependantBuilds"   

########################################################################  
# Create directory for general  
########################################################################  
rm -rf "${GENERATED_LIBRARY_DIR}"  
mkdir "${GENERATED_LIBRARY_DIR}"  
mkdir "${DEVICE_FRAMEWORK_OUT_DIR}"  
mkdir "${FRAMEWORK}"  

########################################################################  
# Copy files Framework  
########################################################################  
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"  

########################################################################  
# Make a binary for device ie. arm7, arm7v, arm8 file system  
########################################################################  
# For Swift framework, Swiftmodule needs to be copied in the universal framework   
if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then  
cp -f "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/"* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo  
fi  
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"  
########################################################################  
# Copy device build library in output folder  
########################################################################  
mkdir -p ${DEVICE_LIBRARY_OUT_DIR}  
cp -r "${FRAMEWORK}" "$DEVICE_LIBRARY_OUT_DIR" 

echo "Device Lib Path ---->" "${DEVICE_LIBRARY_PATH}" "<----"  

# Copy device build library in output folder  
# Create Cross Platform Output
########################################################################  
cp -r  "${DEVICE_LIBRARY_OUT_DIR}/" "${OUTPUT_DIR}/"
lipo -create "${DEVICE_LIBRARY_OUT_DIR}${PROJECT_NAME}.framework/${PROJECT_NAME}" "${SIMULATOR_LIBRARY_OUT_DIR}${PROJECT_NAME}.framework/${PROJECT_NAME}" -output "${OUTPUT_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then  
    open "${OUTPUT_DIR}//"  
fi  


图5.png

同上面的步骤,修改工程中的Target配置

Enable Bitcode 设置为==NO==

Edit Scheme - Run - Info - Build Configuration ==Release==

3.2、Demo工程的创建与配置

1、创建Demo工程

创建一个空白iOS工程,关联到当前workspace。

2、关联SDK工程

在Demo工程设置==Link Binary With Libraries==,加入SDK工程编译生成的framework,如图6所示。

图6.png

3.3、SDK开发

1、SDK功能开发

在DemoSDK中添加源码文件,开发对应的功能。本例中添加一个简单的VC作为示例,

图7.png

添加测试用的图片资源,

图8.png

将新添加的代码头文件添加到SDK的Public Header中,

图9.png

在SDK头文件中,引用新建的源码头文件

图10.png

将SDK中Building Phases中的Copy Bundle Resources中的图片资源或者xib等移除掉,后续会加入到SDK专属的Bundle文件中。

图11.png

在修改SDK工程的源码之后,清理并重新编译工程。

2、SDK Bundle生成

在SDK中的Bundle Target中,Copy Bundle Resources处添加对应的资源,

图12.png

编译Bundle Target,在SDK工程目录中的Products目录下找到相应的.bundle文件,将其复制到SDK Demo工程所对应的文件中。然后在SDK Demo中的Copy Bundle Resouces里面添加刚才的.bundle文件。

图13.png

3.3、SDK调试

此时在SDK Demo工程当中,引用SDK 头文件,测试SDK提供的功能和视图。

图14.png

在模拟器中Run工程,在SDK源码中添加断点,然后在模拟器中查看实际效果。

图15.gif

四、手动应用SDK

4.1 生成Framework

选择SDK工程的Cross Target,编译运行Target,执行配置好的生成脚本,就打包好可以在模拟器与真机上都可成功运行的.framework文件。

4.2 使用SDK

类似于步骤3.2,将SDK的文件添加到目标工程中。

4.3 开发工程

参考

一、包含 Bundle 资源的 framework 的正确打包方式

二、iOS SDK开发(静态SDK)

三、iOS静态库SDK制作(包含第三方静态库)

四、Xcode中的 workspace, project, target, scheme

五、Fat Framework Script for Xcode 10?

六、iOS 静态库,动态库与 Framework

七、iOS中Framework Library嵌套使用

八、jverkoey/iOS-Framework

相关文章

  • iOS开发笔记---- 键盘、静态库、动画、Crash定位

    iOS开发笔记---- 键盘、静态库、动画、Crash定位 iOS开发笔记---- 键盘、静态库、动画、Crash定位

  • Framework 动态库 & 静态库

    关于 动态库 & 静态库 ,参考下面文章:iOS开发关于"框架"的那些事iOS 静态库,动态库与 Framewor...

  • iOS 静态库制作❣进阶

    如果没有看过 基础篇,从这里进入iOS 静态库制作❣基础篇。如果没有看过 中篇,从这里进入iOS 静态库制作❣中篇...

  • iOS静态库开发基础

    一、为什么用库 1、为了方便共享源代码,在分享的同时又不愿意暴露源代码及具体实现 2、实现iOS程序组件化,可以把...

  • iOS SDK(二):Bundle

    iOS SDK开发系列:iOS SDK(一):静态库、动态库创建&接口测试iOS SDK(二):Bundle......

  • iOS 打包静态库.a文件(真机版 + 虚拟机)

    iOS 打包静态库.a文件(真机版 + 虚拟机) 我们以打包IOS开发中封装的高地地图基础功能包 GDMap为例。...

  • iOS 静态库

    iOS 静态库 iOS 静态库

  • iOS 静态库制作❣中篇

    如果没有看过 基础篇,从这里进入iOS 静态库制作❣基础篇。提示:开源光荣 与学习静态库的制作没有任何关系。将自优...

  • iOS 静态库开发

    iOS 静态库开发 本文旨在说明静态库制作中的一些常见问题和特殊处理1. 打包静态库需要的相关问题和设置 静态库中...

  • iOS 创建.a 静态库

    iOS开发中静态库(.a)制作 Xcode 9一般iOS 开发者都会引用第三的库 库根据根据源代码的公开情况 分为...

网友评论

    本文标题:iOS静态库开发基础

    本文链接:https://www.haomeiwen.com/subject/ksvtjctx.html