前言
随着项目功能的扩展,开发人员增多,代码越来越庞大,导致代码混乱、编译变慢等一系列问题。可以尝试采用静态库的方式,每个人负责的模块独立编译成静态库,最后再引入到项目中去。当然如果写的代码需要保密,不想给其他人看到,或者自己写的工具类不同的项目中都需要用的话,静态库也是不错的办法。
基本概念
- 静态库
存在.a和.framework两种形式。
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
简单可以这么说,.a + .h + sourceFile = .framework,所以创建静态库最好还是用.framework的形式。 - 动态库
存在.framework和.tbd两种形式。 - 静态库和动态库的区别
静态库在编译链接时, 会被完整的赋值到可执行文件中;动态库在程序运行时动态加载到内存中, 系统只会加载一次。 - 架构
查看静态库对应的构架: lipo -info Xxx.a
模拟器架构有i386、x86_64
真机架构有armv7、armv7s、arm64
创建静态库项目
-
Xcode -> File -> New -> Project... -> 选择Cocoa Touch Framework
创建静态库工程.png
Cocoa Touch Framework编译生成.framework文件。
Cocoa Touch Static Library编译生成.a文件。 -
修改Target的Build Settings
Build Active Architecture Only改成No
image.png
Dead Code stripping改成No
Link With Standard Libraries改成No
Mach-O Type改成Static Library
image.png -
在Build Phases的Headers中公开.h文件
image.png
4.编译
image.png
编译生成的.framework文件可以用lipo -info xxxSDK.framework/xxxSDK查看支持的架构,可以用lipo -create 命令合并.framework。用lipo命令不是很方便,下面通过添加一个target运行脚本的方式导出静态库。
5.导出静态库
选中TARGETS下面的xxxSDK,Editor -> Add Target...
image.png
选择Cross-platform,选择Other下面的Aggregate -> Next
image.png
选中TARGETS下面新生成的xxxSDKRun,切换到Build Phases面板,点击 + ,点击弹出的New Run Script Phase
image.png
在新生成的Run Script的Shell下加入以下运行脚本
image.png
运行脚本
#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}_Products/"
#创建输出目录,并删除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
#分别编译模拟器和真机的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#拷贝framework到univer目录
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"
#合并framework,输出最终的framework到build目录
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
#删除编译之后生成的无关的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done
#判断build文件夹是否存在,存在则删除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
#打开合并后的文件夹
open "${UNIVERSAL_OUTPUT_FOLDER}"
Scheme选择xxxSDKRun,Build即可生成最终使用的.framework文件。(一定要先选中xxxSDK,Build成功之后才行)
image.png
后记
- 在要使用.framework的项目中拖入.framework文件即可,import .h文件时,需要以#import <xxxSDK/Utils.h>这样的形式导入。
- 如果静态库需要引入第三方库,可以使用pod的形式,第三方库不会打包进.framework中,避免重复引用。
3.如果静态库需要用到图片等资源文件,可以导入bundle。 - .h文件比较多的时候,可以把.h文件统一引入到一个.h文件中,在项目中只引入这个.h文件即可。
网友评论