CocoaPod安装
-
安装命令,要求输入的密码是
Mac
的开机密码
sudo gem install cocoapods
如果还是不行,可以试试下面的命令:
sudo gem install -n /usr/local/bin cocoapods
-
如果很慢,一般是镜像源的问题,可以用下面的命令查看一下
gem sources -l
输出如果是下面这样的,应该很快就能安装成功
*** CURRENT SOURCES ***
https://gems.ruby-china.com/
CocoaPod Package安装
这是CocoaPod
的打包工具,需要额外安装,安装命令,也是要输入Mac
开机密码的。
sudo gem install cocoapods-packager
cocoapods-packager链接地址
Oh no, an error occurred问题: 在用--dynamic参数打包的时候,发生了这个问题。cocoapods的版本是1.8.4;网上有文章说是版本问题,解决办法就是移除当前的版本,安装可用的版本1.5.3。安装命令: gem install cocoapods -v 1.5.3
[花絮] Oh no, an error occurred,坑爹的cocopods1.6.0
从这篇文章可以看出,这个bug
是cocopods1.6.0
开始引入的,到现在cocopods1.8.4
仍然没有解决。
初始化创建
比如,现在决定要开发一个名字叫ZZKit
的库文件。可以打开终端,输入如下命令:pod lib create ZZKit
接下来是回答问题,类似下面这样的:
命令执行完之后,就自动打开XCode,并且生成了框架文件:
Find中的文档结构:
Xcode中的视图:
例子工程可以运行,是一个空白页面
配置为本地系统
现在的目标是输出一个库(.a,.framework)给其他人用,暂时还没用代码复用或者工程组件化的需求,所以直接配置为本地系统
- 编辑
ZZKit.podspec
配置文件
检查配置文件:pod lib lint --allow-warnings
验证格式是否正确
如果出现错误:
- ERROR | [iOS] unknown: Encountered an unknown error (Could not find a ios simulator (valid values: ). Ensure that Xcode -> Window -> Devices has at least one ios simulator listed or otherwise add one.) during validation.
这是因为CocoaPod不是最新的,执行一下sudo gem install cocoapods 更新到最新版本就可以了。但是,这个时候,打动态包pod package ZZKit.podspec --dynamic --force的时候“Oh no, an error occurred”问题又出现了。
如果出现错误:
xcrun: error: unable to find utility "simctl", not a developer tool or in PATH ) during validation.
是因为Xcode
的Command line Tools
没有配置。菜单位置:Xcode-> Preference...->Location
unable to find utility "simctl"的解决方案
- 创建git本地库。有Sourcetree帮忙,创建本地库很方便。需要打个tag,并且版本号需要和配置文件ZZKit.podspec指定的一致
0.1.0
- 打包,有三种选择
--embedded
(静态的.framework),--library
(静态的.a),--dynamic
(Embedded的.framework)。这次选择--library
,比如微信的WeChatSDK就是.a
输入打包命令:pod package ZZKit.podspec --library --force
打包完成后,会生成一个工程名和版本名字拼接成的文件夹(这里是ZZKit-0.1.0),并且支持模拟器和真机,常见的五种架构都支持。
用file命令可以验证模拟器和手机都支持:
image.png
- 这个功能挺赞的,省去了手敲lipo命令的麻烦。
- 一般Pod都是最新的,所以动态库就不方便了。用library参数,打包静态库还是挺好的。
- 什么参数都不加,默认的就是静态类型的
framework
。这个和--embedded
参数的区别是文件夹的结构不一样。
文件结构
-
如果希望生成的文件生效,那么必须要执行
pod install
命令,不然的话,example
工程中的文件是无法调用开发的文件的。 -
代码文件必须放在
ZZKit/Classes
目录下面,不然的话pod install
会直接删除文件。感觉就是文件突然消失了,然后出一堆的error
,让人吓一大跳。 -
在
Xcode
中的文件目录和实际的文件夹位置是不一样的。就算把Classes
和Asset
这两个目录带入Xcode
,执行一下pod install
之后也会自动消失,原因还不清楚。
资源访问
资源配置
-
CocoaPod
会生成一个和.framework
或者.a
相同名字的.bundle
文件,统一存放资源文件。 -
图片和故事版都可以当做资源文件来看待。
-
资源文件都放在一个叫
Asset
的文件夹中,和Classes
文件夹同一级别。比如:
- 执行
pod install
之后,会在工程视图中生成一个叫Resources
的目录
-
注意:资源文件夹
Asset
不要有子目录,不然的话自动生成的Resources
会显示两份,比较难看。 -
打包之后,会生成一个和库名相同的
.bundle文
件,里面会有Asset
文件夹下的资源文件。
-
Assets.xcassets
是不能用的,pod install
的时候会出错。所以图片直接放在Asset
文件夹下。 -
ZZKit.podspec文件中,要把资源文件夹的目录声明出来。
s.resource_bundles = {
'ZZKit' => ['ZZKit/Assets/*']
}
资源读取
- 根据
bundle
和库同名这个特点,需要先获取资源的bundle
。
NSBundle *exeBundle = [NSBundle bundleForClass:[self class]];
NSString *resourceBundlePath = [exeBundle pathForResource:@"ZZKit" ofType:@"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
exeBundle:
是指可执行文件的bundle
,如果是静态库,那么就是mainBundle
,库代码会合并进入mainBundle
,资源文件,(包括故事版,图片等),不会并入。如果是动态framework
,那么就是只动态framework
本身。动态库的代码和资源都会保持独立,不会并入mainBundle
。resourceBundlePath, resourceBundle:
这里利用了CocoaPod的机制,不管是静态库还是动态库,打包之后,都会有一个库名.bundle
的资源文件bundle
。先找到路径,然后再找到资源文件的bundle
。- 故事版和图片的读取API,都有一个bundle参数。这个参数如果不给,默认就是
mainBundle
。所以,只要给出了正确的资源文件bundle
,那么就能够正确读取了。
- 故事版读取的例子:
// launch log page
+ (void)launchLogPageOn:(UIViewController *)vc {
NSBundle *exeBundle = [NSBundle bundleForClass:[self class]];
NSString *resourceBundlePath = [exeBundle pathForResource:@"ZZKit" ofType:@"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Log" bundle:resourceBundle];
UIViewController *logVc = [storyboard instantiateViewControllerWithIdentifier:@"ZZLogViewController"];
logVc.modalPresentationStyle = UIModalPresentationFullScreen;
[vc presentViewController:logVc animated:YES completion:nil];
}
- 图片读取的例子
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSBundle *exeBundle = [NSBundle bundleForClass:[self class]];
NSString *resourceBundlePath = [exeBundle pathForResource:@"ZZKit" ofType:@"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
UIImage *image1 = [UIImage imageNamed:@"余额" inBundle:resourceBundle compatibleWithTraitCollection:nil];
UIImage *image2 = [UIImage imageNamed:@"电脑" inBundle:resourceBundle compatibleWithTraitCollection:nil];
self.imageView1.image = image1;
self.imageView2.image = image2;
}
上面的代码,不论是静态库还是动态库,都能正确读取资源文件。
导出文件
-
默认情况下,
Classes
目录下的所有文件都会被导出。 -
很多时候,这是不必要的,一些内部的
h
文件,没必要让调用者看到。一种更好的做法,就是只导出一个文件,让使用者更方便。就像AFNetworking
做得那样。 -
在
ZZKit.podspec
配置一下,就可以做到这一点。
s.public_header_files = 'ZZKit/Classes/ZZKit.h'
企业微信截图_8e34186c-3772-452e-91f7-5c6640155165.png
参考文章
背景介绍
-
Mac
系统版本:10.15.1 Catalina
-
Xcode
版本:11.3.1
; - 曾经开发过
Framework
,并且是Framework
动态库。iOS Framework开发实践-2019这个是没有借助CocoaPod
,纯手动的。 - 这次借助了
CocoaPod
,还是本地的,只是为了打包方便一点,并且命令行自动生成框架,确实省力。不过CocoaPod
打包动态库是有问题,打包成静态Framework
是比较好的,就是不额外加参数,默认的那个。头文件和资源文件都有,比较方便。
参考文章
cocopods 中的动态库、静态库和framework
使用CocoaPods开发lib库
CocoaPod 私有库的使用方式
网友评论