一.创建一个工程xxx
- 把需要开源的文件放到这个工程对应文件夹里,保证运行成功。(文件夹也会显示到开源库的目录结构),比如
Category
文件夹,对应NSURLSession
二.github创建一个仓库,并把工程xxx
与这个仓库绑定(github实在太慢,用coding创建仓库替代了)
- 上传代码到仓库后,记得打tag:
(cocoapods的版本记录就是这个tag)
git tag 1.0.0 git push --tags
- 码云coding仓库的创建与本地工程绑定
三. 安装CocoaPods
- 没有安装cocoapods,m1芯片安装cocoapods
- 更新cocoapods版本:
pod --version //查看版本 sudo gen install cocoapods pod setup //低于0.33,需要更新
四.配置.podspec文件
-
注册:
(已经注册的先忽略)
pod trunk me
-
创建.podspec:
pod spec create xxx //xxx为开源库的名称
-
编辑.podspec:
-
开源的一些编辑:
Pod::Spec.new do |spec| spec.name = "xxx" //开源库名 spec.version = "1.0.0" //开源版本号,对应仓库的tag spec.summary = "iOS开发组件化" // 简介 spec.description = <<-DESC 一些开发组件化 //描述 (DESC不能删掉) DESC spec.homepage = "https://e.coding.net/xxx.git" //开源库的仓库地址 # spec.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
-
开源协议的编辑:
(coding码云没有license,可以到github下载一个放到仓库)
spec.license = { :type => "MIT", :file => "LICENSE" }
-
作者信息的编辑:
#spec.author = { "tucici" => "[email protected]" } spec.author = "tucici" // 二选一
-
开源库发布的平台的编辑:
spec.platform = :iOS //这里设置只发布iOS平台 # spec.platform = :ios, "5.0" # When using multiple platforms # spec.ios.deployment_target = "5.0" # spec.osx.deployment_target = "10.7" # spec.watchos.deployment_target = "2.0" # spec.tvos.deployment_target = "9.0"
-
开源库的资源编辑:
spec.source = { :git => "#{spec.homepage}", :tag => "#{spec.version}" }
-
其他常见的写法:
spec.source = { :git => "https://github.com/xxx/xxx.git", :commit => "98emfox" } spec.source = { :git => "https://github.com/xxx/xxx.git", :tag => 1.0.0 } spec.source = { :git => "hhttps://github.com/xxx/xxx.git", :tag => spec.version }
-
commit => "98emfox"
表示pod版本与git
仓库指定的commit= 98emfox
绑定 -
tag => 1.0.0
表示pod版本与git
仓库指定的tag=1.0.0
绑定 -
tag => spec.version
表示pod版本与仓库的tag
保持一致。spec.version
就是.podspec
最开始编辑参数spec.version = "1.0.0"
-
-
-
开源库需要包含的源文件:
spec.source_files = "CCKit", "CCKit/Category/*.{h,m}" spec.exclude_files = "Classes/Exclude" # spec.public_header_files = "Classes/**/*.h" //需要包含的头文件
CCKit
文件夹是与.podspec
同一级,上面配置的结果是,开源库会包含CCKit/Category/里面所有的.h.m
文件 -
开源库依赖静态库/动态库的编辑:
spec.frameworks = "Foundation", "UIKit" //这里就只依赖官方库
-
依赖第三方开源库的编辑:
spec.dependency "AFNetworking", "~> 1.0.0"
-
大体上配置就这样,其实看.podspec的注释,可以大概明白每个配置是干嘛的
-
五.验证.podspec
pod spec lint xxx.podspec --verbose
-
验证成功提示:
xxx.podspec passed validation.
六.成功发布
-
发布:
pod trunk push xxx.podspec
-
成功:
Updating spec repo `trunk` -------------------------------------------------------------------- ------------ Congrats xxx (1.0.0) successfully published September 3rd, 04:29 https://cocoapods.org/pods/xxxx Tell your friends!
-
搜索发布的开源库xxx:
rm ~/Library/Caches/CocoaPods/search_index.json
pod repo update
过几分钟后,搜索,就能成功显示,有时候可能需要等更久
:pod search XXX
-
删除已发布的版本:
pod trunk delete ZHPageView 1.0.0
七.错误及解决:
-
Specs satisfying the `xxxx (~> 1.0.0)` dependency were found, but they required a higher minimum deployment target.
:
解决:三方依赖库xxxx
设置里支持最低的ios
版本,所以本开源库设置ios版本要高于xxxx
支持的ios
版本 -
Encountered an unknown error (/usr/bin/xcrun simctl list -j devices
:
解决: Xcode->Preferences->Locations->Command line tools,选择一个Xcode版本 -
[!] The spec did not pass validation, due to 3 warnings (but you can use `--allow-warnings` to ignore them).
:
解决:pod spec lint xxx.podspec --verbose --allow-warnings
八.注意:
- 每次更新完库文件,同时也要更新远程仓库的tag,在验证
pod spec lint xxx.podspec --verbose
的时候,要先把本地tag
删掉,否则会报错xxxx...HEAD...xxxx
错误 - cocoapods本地有对应缓存,有时候即使已经改的可以发布了,由于设置的版本
spec.version = "1.0.0"
,在本地已经有缓存了,验证发布的时候还是会报错,需要清理下本地缓存:pod cache list
,找到相应文件路径,清理。
九.tag相关命令行:
- 查看本地tag:
git tag
- 创建本地tag:
git tag 1.0.0
- 创建含附注tag:
git tag -a 1.0.0 -m '附注信息'
- 查看详情日志:
git log
- 对历史commit打tag:
git tag v1.0.0 06c0b98//(历史commit日志)
- 删除本地tag:
git tag -d v1.0.0
- 删除远程tag:
git push origin --delete tag 1.0.0
- 删除远程分支:
git push origin --delete 远程分支名字
- 推送指定tag到远程:
git push origin 1.0.0
十.OC与Swift混编,有子文件夹的开源库
- OC与Swift混编到pods开源库:
-
- 一个开源库里不仅有OC类,还有Swif类。
-
- 并且在这个开源库里, Swift与OC还会互相调用。
-
- 并且Swift和OC还混合存在于不同的文件夹。
-
-
并且要求发布的开源库在pods里不是一股脑在一个文件夹显示所有文件,而是跟在project中一样,也就是说,如图:
-
-
- 解决:
- Swift调用OC好说,跟平常app开发一样,在桥接文件里导入OC的头文件
- OC调用Swift
- oc文件引用 :
#if FMWK #import
#else #import "XXXKit_Swift.h"///这文件是复制XXXKit-Swift.h的内容 #endif - swift 类文件:
@objc public class NotifyTool:NSObject { @objc public class func add(_ observer:Any){} }
- swift 扩展分类文件:
@objc public extension NSString{ func color(_ alpha : Float) -> UIColor{ return (self as String).color(alpha)} func color() -> UIColor{return (self as String).color()} }
- 问题1:
会报某个文件夹的OC文件里找不到Swift方法的错误
, 原因是找不到XXXKit-Swift.h
里的对应的方法-
XXXKit_Swift.h
这个文件是XXXKit-Swift.h
的拷贝。因为app开发用到XXXKit-Swift.h
就可以了。但是开源库不同文件夹里的OC调用不同文件夹的Swift方法,相当于不同project的OC调用不同project的Swift方法。那么在开发开源库的project里生成的XXXKit-Swift.h
,就包含了所有不同文件夹的Swift方法,我们所需要的就是新建一个.h文件,拷贝XXXKit-Swift.h
的内容,哪个文件夹的OC需要调用Swift,就把这个.h保存一遍。在开发开源库的p roject的Run Script添加脚本如下:
-
generated_header_file=${DERIVED_SOURCES_DIR}/*-Swift.h
# include_dir=${BUILT_PRODUCTS_DIR}/include/${PRODUCT_MODULE_NAME}/
include_dir=${BUILT_PRODUCTS_DIR}/include/${PRODUCT_MODULE_NAME}/
# 将编译器生成的 xxx-Swift 头文件拷贝到 build 目录下的 include 目录中
#mkdir -p ${include_dir}
#cp ${generated_header_file} ${include_dir}
# 去掉 xxx-Swift.h 文件头部注释中的编译器的版本号
sed -i "" "s/^\/\/ Generated by Apple.*$/\/\/ Generated by Apple/g" ${generated_header_file}
# 拷贝 xxx-Swift.h 文件到工程源码目录
header_file_in_proj=${SRCROOT}/${PROJECT}-Swift.h
needs_copy=true
if [ -f "$header_file_in_proj" ]; then
echo "${header_file_in_proj} 已存在"
new_content=$(cat ${generated_header_file})
old_content=$(cat ${header_file_in_proj})
if [ "$new_content" = "$old_content" ];then
echo "文件内容一致,无需再Copy:"
echo "${generated_header_file} "
echo "${header_file_in_proj} "
needs_copy=false
fi
fi
if [ "$needs_copy" = true ] ; then
echo "文件内容不一致,需要Copy:"
echo "复制文件: "
echo "${generated_header_file} "
echo "${header_file_in_proj} "
cp ${generated_header_file} ${header_file_in_proj}
fi
# 拷贝 xxx-Swift.h 文件到开源库根目录得 /Extension文件夹下
header_file_in_path=${SRCROOT}/${PROJECT_NAME}/${PROJECT_NAME}/Extension/${PROJECT}_Swift.h
needs_copy_path=true
if [ -f "$header_file_in_path" ]; then
echo "${header_file_in_path} 已存在"
new_content=$(cat ${generated_header_file})
old_content=$(cat ${header_file_in_path})
if [ "$new_content" = "$old_content" ];then
echo "文件内容一致,无需再Copy:"
echo "${generated_header_file} "
echo "${header_file_in_path} "
needs_copy_path=false
fi
fi
if [ "$needs_copy_path" = true ] ; then
echo "文件内容不一致,需要Copy:"
echo "复制文件: "
echo "${generated_header_file} "
echo "${header_file_in_path} "
cp ${generated_header_file} ${header_file_in_path}
fi
- 问题2:
会报某个文件夹的Swift文件里找不到OC方法的错误
, 原因是Swift文件夹里找不到桥接文件.h
,如果可以,也把桥接文件
一样拷贝到Swift存在的文件夹里。 - 问题3: 生成带子文件夹的.podspec配置
spec.source_files = "XXX/header/*.{h,m,swift,strings}"///总的开源库,
# spec.exclude_files = "Classes/Exclude"
spec.public_header_files = "XXX/header/*.h"
#spec.prefix_header_file = "XXX/header/PrefixHeader.pch"
///依赖的本地子开源库(project)的一个文件夹,这个库在开发project的文件夹名 = ```header ```
spec.subspec 'XXX' do |ss|
ss.source_files = 'XXX/header/**/*.{h,m,swift,strings}
end
///依赖的本地子开源库(project)的一个文件夹,这个库在开发project的文件夹名 = ```header ```
spec.subspec 'CCTool' do |ss|
ss.source_files = 'XXX/CCTool/*.{h,m,swift,strings}'
ss.dependency 'XXX/CCTool'DSSss.dependency 'TCCKit/公用组件'
ss.dependency 'TCCKit/Extension'
end
- 一切正常的话,就会发布个XXX开源库,XXX下面有两个文件夹
heade
和CCTool
-
总结:所有找不到文件,都是某个地方没设置好。一个一个检查,总能解决问题。
-
- 一个开源库的总文件下的各个子文件夹,其实就相当于根文件夹下面依赖了不同的库,只不过这些库么有发布到cocoapods,是一起的,因此要设置好.podspec文件依赖关系
(重复问题3的办法)
,要避免循环依赖。
- 一个开源库的总文件下的各个子文件夹,其实就相当于根文件夹下面依赖了不同的库,只不过这些库么有发布到cocoapods,是一起的,因此要设置好.podspec文件依赖关系
- 2.在验证库时候,可能会一直出现找不到响应的方法/类等错误,这个就是不同文件夹的OC/Swift互相调用的问题了,说白了,就是
XXX-Swift.h
和桥接文件
没引用好。在同一个工程,我们可以直接把XXX-Swift.h
和桥接文件
,导入到PrefixHeader.pch
,就可以了。(重复问题1/问题2的办法)
-