制作framework并发布Cocoapods私有库【Swift】

一、制作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/'

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容