一、制作framework
1.创建APP工程,用来开发framework和测试
2.创建framework的Target,根据项目需要来命名,此处命名为TestSDK,创建步骤如下:
3.工程使用pod管理依赖三方库
使用终端cd到工程根目录,执行命令
pod init
,打开生成的Podfile文件,添加framework所需的第三方库,如pod 'SnapKit'
,并执行pod install
,然后打开TestDemo.xcworkspace
文件
4.配置framework
设置支持版本
取消只编译当前架构
移除重复的架构
真机和模拟器编译后,framework中arm64架构重复,会导致合并失败,所以移除模拟器中的arm64架构
设置编译选项优化,给framework包瘦身
设置类型为静态库
Scheme切换到TestDemo,设置release
5.开发功能代码
如果让类和方法让外界可调用,需要用权限修饰,使用public,如果要提供OC调用,要使用@objc修饰
swift 不像OC可以暴露接口,在swift中 要想给别的工程调用接口,记得在类,方法或属性前加public。
swift权限控制符:
open 权限最大,可以被外界模块访问,继承重写
public 可以被外界工程访问
internal 默认文件创建时的权限,可以在本工程的访问
private 只可以在创建的文件内访问
5.1.framework中的资源文件的使用
1).图片资源
extension UIImage {
class func ex_image(named name: String) -> UIImage {
//图片放到 framework 的 bundle 中可使用
let bundleName = "TestSDK.framework/ImageBundle.bundle/\(name)"
if let image = UIImage(named: bundleName) {
return image
}
return UIImage()
}
}
2).文件资源
文件资源也可以放在bundle中,同样的调用方式
var filterData: [FilterModel] = load("filters.json")
func load<T: Decodable>(_ fileName: String, as type: T.Type = T.self) -> T {
let data: Data
let mainBundle = Bundle.main.path(forResource: "TestSDK.framework/ImageBundle", ofType: "bundle")
let fileBundle = Bundle.init(path: mainBundle ?? "")
let path = fileBundle?.path(forResource: fileName, ofType: nil) ?? ""
let file = URL(fileURLWithPath: path)
do {
data = try Data(contentsOf: file)
} catch {
fatalError("无法初始化\(fileName)文件")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("无法解析\(fileName)文件")
}
}
6.添加生成最终需要发布的framework的脚本
说明:关于framework编译和合并的脚本,我还是比较喜欢以下的方式,简单粗暴。
像新建一个shell脚本的target我也试过,framework中没有依赖三方还行,像我这种依赖三方库的,shell运行不通过,三方库会报错
# 真机和模拟器framework合并脚本
# 选中framework,分别在真机和模拟器编译成功即可
if [ "${ACTION}" = "build" ]
then
# 定义framework名称(替换为自己定义的名字即可)
SDK_NAME=TestSDK
# 输出路径
INSTALL_DIR=${SRCROOT}/Products/${SDK_NAME}.framework
# 真机路径
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${SDK_NAME}.framework
# 模拟器路径
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${SDK_NAME}.framework
# 如果输出路径已存在,则删除
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
# 创建输出路径
mkdir -p "${INSTALL_DIR}"
# 如果真机framework和模拟器framework都存在
if [ -d "${DEVICE_DIR}" ] && [ -d "${SIMULATOR_DIR}" ]
then
# 拷贝真机framework到输出路径
cp -r "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# 拷贝模拟器framework中的modules到输出路径
cp -r "${SIMULATOR_DIR}/Modules/${SDK_NAME}.swiftmodule/" "${INSTALL_DIR}/Modules/${SDK_NAME}.swiftmodule"
# 合并真机framework和模拟器framework
lipo -create "${DEVICE_DIR}/${SDK_NAME}" "${SIMULATOR_DIR}/${SDK_NAME}" -output "${INSTALL_DIR}/${SDK_NAME}"
fi
fi
7.生成framework
选中TestSDK,分别在真机和模拟器编译一次即可,然后在项目的根目录中,Products文件夹里会有最终的framework
二、发布framework
cocoapods发布私有库的大致流程为:
1、GitHub上创建一个私有索引库,这个索引库存放的都是私有库的路径
2、GitHub、码云或者Coding等上创建一个私有库,存放的是整个私有库的所有源码
3、把私有库的.podspec文件push到私有索引库中
4、把私有索引库更新到本地repo中
1.创建私有索引库,并添加到本地repo中
终端执行pod repo add TestSpec https://github.com/rayraychow/TestSpec.git
然后执行pod repo
即可查看有没有添加成功,有TestSpec即是成功
2.创建framework库
3.本地framework源码根目录下,创建.podspec文件
终端执行pod spec create TestSDK
生成文件后拖入Xcode工程中,取消copy勾选
podspec文件修改完后,把本地私有库代码和远端私有库关联,并把代码都push上去
1).git add .
如果报错fatal: not a git repository (or any of the parent directories): .git
,使用git init
创建git目录
2).git commit -m '修改的内容'
3).git push
4).git tag '0.0.1'
5).git push --tags
注意:每次push后都需要打tag,且tag和.podspec文件中的版本号要一致
如果报错Ld .../Build/Intermediates.noindex/App.build/Release-iphonesimulator/App.build/Objects-normal/arm64/Binary/App normal arm64
,
在podspec文件中加入:spec.pod_target_xcconfig = { 'VALID_ARCHS' => 'x86_64 armv7 arm64' }
Pod::Spec.new do |spec|
spec.name = "TestSDK"
spec.version = "0.0.1"
spec.summary = "A short description of TestSDK."
spec.description = <<-DESC
这是描述区,这里的文字一定要比 spec.summary 中的内容长,
否则spec远端验证可能会不通过
DESC
# 这里是主页地址,可以写github私有库的主页地址
spec.homepage = "https://github.com/rayraychow/TestSDK"
spec.license = "MIT"
spec.author = { "贝勒" => "beile@jravity.com" }
# 这是可以应用的平台及系统限制
spec.platform = :ios, "12.0"
# 这是私有库的路径,填写私有库的git clone 的链接就行
spec.source = { :git => "https://github.com/rayraychow/TestSDK.git", :tag => "#{spec.version}" }
# 如果是想暴露源码,打开这行
# spec.source_files = "Classes", "Classes/**/*.{h,m}"
# spec.exclude_files = "Classes/Exclude"
# 此处暴露的是framework
spec.vendored_frameworks = "Products/TestSDK.framework"
# 此处声明swift版本
spec.swift_versions = "5.0"
# 此处声明支持的类型
spec.pod_target_xcconfig = { 'VALID_ARCHS' => 'x86_64 armv7 arm64' }
# 这是声明framework依赖的三方库
spec.dependency "SnapKit"
end
4.校验podspec文件
1).本地校验:pod lib lint
2).从本地和远程验证:pod spec lint
3).依赖库(spec.dependency)中 如果包含.a文件,验证的时候出现错误。加上这个来让验证通过:--use-libraries
4).有警告导致不通过验证时,加上这个忽略警告:--allow-warnings
5).有错误导致不通过验证时,加上这个查看具体错误:--verbose
校验文件可以直接执行pod spec lint --allow-warnings
注意:进行验证时如果报错warning: Could not find remote branch 0.1.0 to clone. fatal: Remote branch 0.1.0 not found in upstream origin
说明没有上传代码到仓库,先进行代码上传,执行 git add . git commit git push ,然后 git tag等流程的上传。
5.把.podspec文件push到远程Spec私有索引库中
终端执行pod repo push TestSpec TestSDK.podspec --allow-warnings --skip-import-validation
如果出现
[!] Found multiple specifications for `SnapKit (0.17.0)`: -/Users/beile/.cocoapods/repos/master/Specs/1/f/6/SnapKit/0.17.0/SnapKit.podspec.json -/Users/beile/.cocoapods/repos/trunk/Specs/1/f/6/SnapKit/0.17.0/SnapKit.podspec.json
时,加入命令--sources='https://github.com/CocoaPods/Specs.git'
6.发布podspec文件到公有库中
1).注册cocoaPods
终端执行pod trunk register 邮箱地址 '用户名' --verbose
这里我们一般使用github邮箱和用户名, 然后在你的邮箱中会收到确认邮件, 在浏览器中点击链接确认即注册成功。
2).验证cocoaPods
确保打开了邮件中的链接之后(正常加载出来就行),继续执行命令
pod trunk me
3).发布
pod trunk push TestSDK.podspec
该命令的执行过程:
a.更新本地 pods库 ~/.cocoaPods.repo/master
b.验证*.podspec格式是否正确
c.将 *.podspec 文件转成 JSON 格式
d.对 master 仓库进行合并、提交
7.使用(和正常的pod库使用方式一样)
唯一的区别是,因为是私有库,需要在podfile文件中额外添加源地址
一个是私有的索引库地址source 'https://github.com/rayraychow/TestSpec.git'
一个是cocoapods的cdn地址source 'https://cdn.cocoapods.org/'
网友评论