Framework制作到打包

Framework制作流程

坑:由于oc的分类会覆盖同名的方法, 在framework中一定要谨慎对待分类

1. 新建framework 项目

File > New > Project

create.png

2. 需要注意配置的地方

1.配置sdk运行最低支持的iOS版本
当sdk是为项目定制时,直接配置跟项目运行版本一致即可;
当sdk是封装了开放给别的开发者使用时,使用大众版本,如目前大多应用都需要iOS9及以上
2.静态库or动态库选择
首先要搞清楚静态库和动态库的区别,这里有介绍
在这里,我选择了使用静态库的形式,配置:Build Settings > Mach-O Type 可以配置静态库/动态库
3.Build Phases > Headers
Public: 需要暴露给外部的.h文件,只有在public中的.h文件,才能被外部直接使用

3.新建target测试demo

新建一个target用来测试(File > New > Target > Single View App)


屏幕快照 2020-06-15 上午10.53.39.png

如图,Products>MyTestSDK.framework 产物勾选,现在在Demo中就可以引用SDK中的文件了

#import

屏幕快照 2020-06-15 上午11.04.06.png

4.集成第三方库

项目开发中会使用到很多第三方库(AFN,SD等),那么在sdk中集成第三方库的时候最方便的是使用pods来管理了

在使用的过程中只需要sdk中和使用sdk的项目保持第三方库的版本一致即可。

  1. 创建pod文件,分别添加两个target所依赖的第三方库(注意:使用到的相同第三方库需要保持版本一致)

  2. 因为sdk中使用了pod管理依赖库,所以当sdk开发完成,提供别别人使用时,需要同时提供podspec文件,当别人使用pod集成你的sdk的时候,podspec会指明sdk所依赖的第三方库,pod init的时候会一并安装

* 使用 pod spec create MyTestSDK 就可以创建一个名为MyTestSDK的podspec文件, 将podspec文件放在项目 ./docs/  目录下

* podspec文件配置需要注意的地方:

  1. resource文件,sdk中需要使用的图标需要新建一个bundle,统一放在bundle中管理,

    spec.resource = "MyTestSDK.framework/*.bundle" 可以包含sdk中的所有bundle文件



  2. spec.dependency 配置,将sdk中依赖的第三方库全都列出来

    spec.dependency 'AFNetworking'

    spec.dependency 'MJRefresh'

    spec.dependency 'YYModel'

5.framework打包脚本

sdk的打包跟需要支持的cpu架构有关,当运行的target选模拟器时,编译出来的framework是支持x86_64和i386的;当运行的target选择真机时,编译出来的framework是支持arm64,armv7等架构;我们需要做的是将支持两个架构的可执行文件合并,生成既支持模拟器,也支持真机运行的包,脚本如下:


  #!/bin/sh

# 合并在真机和模拟器上编译出的 Framework

# 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME

FMK_NAME="MyTestSDK"

# 在工程的根目录创建framework的文件夹.

INSTALL_DIR="./build/MyTestSDK/${FMK_NAME}.framework"

WRK_DIR="./build"

DEVICE_DIR="./build/Build/Products/Release-iphoneos/${FMK_NAME}.framework"

SIMULATOR_DIR="./build/Build/Products/Release-iphonesimulator/${FMK_NAME}.framework"

# Clean两个架构的framework

xcodebuild clean -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphoneos

xcodebuild clean -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphonesimulator

# build iphoneos

xcodebuild -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphoneos build -derivedDataPath ${WRK_DIR}

# build simulator

xcodebuild -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphonesimulator build -derivedDataPath ${WRK_DIR}

# 删除之前生成的framework

if [ -d "${INSTALL_DIR}" ]

then

rm -rf "${INSTALL_DIR}"

fi

mkdir -p "${INSTALL_DIR}"

cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"

# 合成同时支持真机和模拟器架构的 framework

lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"

# 文档, 将生成好的podspec文件拷贝到 framework目录下

cp "./docs/MyTestSDK.podspec" "./build/MyTestSDK/"

#移除多余文件

rm -rf "./build/Build"

rm -rf "./build/Logs"

rm -rf "./build/SourcePackages"

rm -rf "./build/ModuleCache.noindex"

6. 最后的项目结构 & 需要提供的产物

屏幕快照 2020-06-15 上午11.50.51.png

如图,./build/MyTestSDK/ 目录下的 MyTestSDK.framework 和 MyTestSDK.podspec 就是需要提供给别人使用的

7. 如何集成导出的framework到项目中使用

只需要将第6步中导出的产物放到项目目录下,然后使用pod集成就可以了

  1. 在项目的pod 中加入:pod 'MyTestSDK', :path => './MyTestSDK'
  2. pod install, ok 大功告成!

遇到问题及解决办法

  1. 关于第三方库引用,怎么避免类重名?

使用pods来管理第三方依赖库

  1. 关于在静态库中使用分类时报错 unrecognized selector sent to instanceunrecognized selector sent to instance?

    如果静态库中有category类,则在使用静态库的项目配置中【Other Linker Flags】需要添加参数【-ObjC]或者【-all_load】。

  2. 不能断点调试framework中的源码?
    调试中发现在framework的源码打断点没有效果, 排查后发现是因为 framework target的 Generate Debug Symbols 设置为NO, 导致的, 改成YES即可 (Generate Debug Symbols 对app target也是相同的效果, 可以缩小framework的包大小, 但是不会生成调试信息, 导致不能断点调试)

  3. 使用lipo合并真机&模拟器framework时报错: have the same architectures (arm64) and can't be in the same fat output file
    在Xcode12之前:
    编译模拟器静态库支持i386 x86_64两架构
    编译真机静态库支持armv7 arm64两架构
    使用lipo -create -output命令可以将两个库合并成一个支持模拟器和真机i386 x86_64 armv7 arm64四种架构的静态库。

但是Xcode12编译的模拟器静态库也支持了arm64,导致出现真机库和模拟器库不能合并的问题。

---> 解决: 在 Build Settings -> Excluded Architectures 设置 Any iOS Simulator SDK : arm64
在打包时, 模拟器上的库就不会在支持arm64架构了, 合并也就没问题了
---> 解决2: 可以使用 lipo xxx.a -remove arm64 -output xxx_no64.a, 将模拟器静态库中的arm64移除, 然后再进行合并

  1. 问题4中连带出的问题, 经过问题4中打包出来的framework同时支持了 真机:arm64、armv7, 模拟器:i386、x86_64 这4种架构, 但是在Xcode13(目前使用的13)或以上使用时, 在模拟器上编译会报错: in XXX.a(XXXXXXX.o), building for iOS Simulator, but linking in object file built for iOS, for architecture arm64
    ---> 模拟器运行需要支持模拟器的arm64, 但是静态库中没有, 所以报错了
    ---> 解决: 在 Build Settings -> Excluded Architectures 设置 Any iOS Simulator SDK : arm64 (Debug模式, 因为运行的时候一般是设置的debug)

你可能感兴趣的:(Framework制作到打包)