缘由

相信所有的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混编代码,这就使得在工程配置和工程的校验中出现很多问题。

常规操作

  1. 使用pod 提供的模板pod lib create YourProjectName进行工程的创建[推荐],这样pod会为你创建整个开发环境包括Example,而你只需要在Development Pods下进行代码库开发即可,使用模板创建时会提供很多选项,根据自身需求选择输入即可或者Google一下,这里就不列出来了。
  2. 注意自己的开源代码,想要暴露出来的类、方法、属性均需要使用public或者open等修饰
  3. 在GitHub创建一个代码Repositories,与刚创建的工程关联起来,并需要打上Tag,该Tag和podspec配置的version一致,这就是你的代码库的版本号了。代码要提交到Cocoapods是需要放到GitHub公开的,因为pod其实也是一个容器。如果想要建私有库,比如说放到付费GitHub用户或者其他代码托管平台Coding, CSDN等,可以自建一个私有库,本文不涉及私有库搭建,可自行Google。
  4. 如果代码很多,最好定期进行pod lib lint的检查,确保所有配置和代码不存在问题,能够及时解决与调整。
  5. 如果引用了其他三方pod库,在podspec中配置s.dependency ‘xxx’,这时要怎么在类库中引用这个库呢,刚开始我真的蒙了,无论怎么import都说找不到,原来改了任何的podspec配置,都要重新在你的Example目录下pod update ProjectName一下,这样正确的配置才能配置到位。
  6. 没有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就可以通过了。

其他

  1. SDK类为Public,其函数引用的参数类型也必须是public或open修饰,所以尽量使用自定义的类型和系统自带的类型,引用一些三方库的类型不一定是public或open
  2. 设置objc标识时注意字母大小写,需要在build setting - other linker flags设置-ObjC (必须写成这样,一个字母都不能写错,不然会报错)
  3. xx.podspec编写中,配置source_files时,*.{h,m,mm},大括号里面用逗号隔开,注意逗号后面不能使用空格,否则空格后面的内容就识别出来了,相当于只配置了空格前面的源文件,只能说要求太严格,对我这种平时习惯打空格的,真的是出错了都不知道原因,切记

终极大招

如果依赖的framework或者.a文件或者其他三方库导入配置无论怎样都包括的话,最后垫底的操作就是使用源代码,把有用的代码抠出来,放到SDK的源码中去,当然这需要一定的时间。

写在结尾

这是自建pod库的遇到的一些问题,仅作为记录,忽略了很多流程说明,但都可以在网上轻松找到,本文提到的有些些错误很刁钻需要仔细才能发现,希望记录后下次遇到能够轻松解决,也希望对大家有用,开源,让世界更美好,让自己更优秀。