缘由
相信所有的iOSer都多多少少会用到Cocoapods进行三方库的管理,尽管现在Swift大多说使用Swift Package Manager, Carthage进行管理,但仍有很多的库如OC代码库,大多数之前的Swift代码库是不支持的,还是使用pod进行管理。
最近公司的代码需要开源并制作成SDK供其他三方厂商使用,考虑到三方库管理平台的使用普及度,选择首先发布到Cocoapods。以下将这个过程中遇到的问题进行记录与分享,主要是包含静态库.a, .framework和OC代码的问题。
小插曲,小实验
由于自己之前从未发布代码到Cocoapods,所以在写公司的SDK之前,自己随意写了一个TouchID/FaceID的代码发布到了Cocoapods平台,传送门TouchIdManager,当时觉得这也太简单了吧。代码里面就一个Swift文件,pod lib lint轻易就通过,pod trunk push也就很快了。不过公司的代码使用了三方的东西,比如NFC蓝牙阅读器SDK(OC代码+.a文件),其他的OC framework,自定义OC混编代码,这就使得在工程配置和工程的校验中出现很多问题。
常规操作
- 使用pod 提供的模板
pod lib create YourProjectName
进行工程的创建[推荐]
,这样pod会为你创建整个开发环境包括Example,而你只需要在Development Pods
下进行代码库开发即可,使用模板创建时会提供很多选项,根据自身需求选择输入即可或者Google一下,这里就不列出来了。 - 注意自己的开源代码,想要暴露出来的类、方法、属性均需要使用public或者open等修饰
- 在GitHub创建一个代码Repositories,与刚创建的工程关联起来,并需要打上Tag,该Tag和podspec配置的version一致,这就是你的代码库的版本号了。代码要提交到Cocoapods是需要放到GitHub公开的,因为pod其实也是一个容器。如果想要建私有库,比如说放到付费GitHub用户或者其他代码托管平台Coding, CSDN等,可以自建一个私有库,本文不涉及私有库搭建,可自行Google。
- 如果代码很多,最好定期进行pod lib lint的检查,确保所有配置和代码不存在问题,能够及时解决与调整。
- 如果引用了其他三方pod库,在podspec中配置s.dependency ‘xxx’,这时要怎么在类库中引用这个库呢,刚开始我真的蒙了,无论怎么import都说找不到,原来改了任何的podspec配置,都要重新在你的Example目录下
pod update ProjectName
一下,这样正确的配置才能配置到位。 - 没有error提示有warning通不过时,加入
--allow-warning
即可,pod lib lint和pod trunk push都需要加。
所遇问题与解决方法
问题1.
Include of non-modular header inside framework module 'eNotesSdk'
原因:一般是因为没有所引用文件不是public权限,默认是project
解决方法:将你引用的代码文件配置到s.source_files,默认情况下source_files下的文件都会是public的,如果发现不是可以在
Xcode -> File inspector ->Target membership
设置成public问题2.
遵循OC中的delegate导致eNotesSDK-Swift.h not found
原因:该类为了可以被外界调用声明成了public,而使用的依赖SDK中存在代理无法设置成public extension或者代理方法不能设置成public从而造成编译错误。
解决方法:这个没有其他别的办法,目前做法是新建了一个非Public修饰的类用以包裹单独处理其业务,然后再该类统一调度使用。
发现:public修饰下的代理也得声明为public,不然要么编译报错,要么该代理不走
问题3.
修改Development Pods后,运行Example报错或崩溃
原因:修改SDK代码后,没有重新编译,还是使用原有的代码
解决方法:重新编译一次,注意最好切换Device的target进行编译,如之前是真机连接需要切换到Generic iOS Device进行编译,否则可能出现编译无效的问题
问题4. `missing required architecture i386 in file
原因:引用的framework不支持i386架构
解决方法:有framework的代码的情况下,加入i386架构支持重新编译,合并framework替换之前有问题的framework
延伸:支持i386后pod lib lint成功,但是pob trunk push还是出现相同问题,后来网上查资料说是因为缓存的原因,我找到了 /Users/useName/Library/Caches/CocoaPods/Pods/External/YourPodName这个缓存路径,发现在pod trunk push的时候生成的缓存里面的还是旧framework,查看架构支持lipo -info果真是不支持i386架构,我目前是把新的新的framework考到了该目录,然后pod trunk push就可以通过了。
其他
- SDK类为Public,其函数引用的参数类型也必须是public或open修饰,所以尽量使用自定义的类型和系统自带的类型,引用一些三方库的类型不一定是public或open
- 设置objc标识时注意字母大小写,需要在build setting - other linker flags设置-ObjC (必须写成这样,一个字母都不能写错,不然会报错)
- xx.podspec编写中,配置source_files时,*.{h,m,mm},大括号里面用逗号隔开,注意逗号后面不能使用空格,否则空格后面的内容就识别出来了,相当于只配置了空格前面的源文件,只能说要求太严格,对我这种平时习惯打空格的,真的是出错了都不知道原因,切记
终极大招
如果依赖的framework或者.a文件或者其他三方库导入配置无论怎样都包括的话,最后垫底的操作就是使用源代码,把有用的代码抠出来,放到SDK的源码中去,当然这需要一定的时间。
写在结尾
这是自建pod库的遇到的一些问题,仅作为记录,忽略了很多流程说明,但都可以在网上轻松找到,本文提到的有些些错误很刁钻需要仔细才能发现,希望记录后下次遇到能够轻松解决,也希望对大家有用,开源,让世界更美好,让自己更优秀。