前言
前几篇博客描述了手动创建组件的方法,到新公司发现这种方式不适合小公司快捷方便的需求,所以转而向cocoapods
为我们提供的pod lib
命令来创建组件,这样对于没接触过组件化的新人比较友好,另外也确实少了很多自己需要配置的各种东西。
准备
- 组件创建需要
cocoapods
- 如果想上传到仓库还需要有
git
- 如果环境都没搭建可以看下之前本序列的文章都有介绍
创建
1、创建组件命令,你可以CD
到特定文件夹下执行命令,创建名为名为Demo的组件为例
# 开始执行以下命令后会去github克隆模板代码没翻墙可能会比较慢
pod lib create Demo
#创建过程中的选项可参考下面,有特殊也可以自己决定
What platform do you want to use?? [ iOS / macOS ] 平台我们选择iOS
> iOS
What language do you want to use?? [ Swift / ObjC ] 语言我选择oc
> ObjC
Would you like to include a demo application with your library? [ Yes / No ] 是否创建demo工程
> Yes
Which testing frameworks will you use? [ Specta / Kiwi / None ] 是否添加测试支持
> None
Would you like to do view based testing? [ Yes / No ] 是否添加测试的view
> No
What is your class prefix? 类名使用的前缀
> GG
当前命令执行完之后,它会帮我们执行pod install
命令并自动打开里面的Example
工程,我们先看下创建后文件夹目录:
- Demo文件夹是我们实际的组件目录,后面创建的图片及文件和源代码都在这里
- Demo文件夹下有两个文件夹,一个
Classes
是存放代码的地方在xcode创建的时候记得把代码的目录选择放这里,一个是Assets
存放不限于图片的其他资源文件一般我们放图片可以创建一个系统的.xcassets
图片管理器很方便存取 - Demo.podspec是组件的描述,不懂可以看下之前的基本概念都是一样的
- Example 是我们调试使用的工程,跟我们平时使用的项目差不多,只是它在
Example/Podfile
中帮我们加入了当前组件的本地依赖方便我们调试
pod 'Demo', :path => '../'
- .git是git相关的你可以删掉它后续自己创建
- .travis.yml是有关自动化相关的也可以先忽略或者直接删除
在xcode中的工程目录:
- 红色部分是调试工程的目录先不管他
- 绿色部分就是我们在调试的时候组件代码具体呈现的地方,
Demo
就是我们组件的名称有多个的话就是多个这样的文件夹,Demo/Pod
中的放的是组件的描述和README.md文件和实际的目录是同步的
2、创建好之后最好到项目根目录下打开.gitgnore
忽略文件中添加下列两行,忽略我们在测试的工程添加的依赖也上传到git上
Example/Pods
Example/Podfile.lock
3、如果有自己的私有库,在Example/Podfile
中替换以下添加私有源,没有的可以忽略这步
source 'git@xxxx/Specs.git'
4、上传到仓库,删掉项目根目录下的git
文件夹,使用以下命令将文件提交至git,嫌麻烦也可以直接使用Sourcetree
来上传
#当组件的根目录下
cd Demo
git init
#关联内网git仓库
git remote add origin git@xxxt/Demo.git
#提交源码
git add .
git commit -m "Initial commit"
git push -u origin master
5、创建源代码文件应注意选择路径,还有对应的target选择
6、图片的读取问题
- 我们可以在xcode中选择
Asset Catalog
来创建一个自己的图片管理器,名字最好用组件名称来命令好区分,一般存放在组件的Assets
目录下
- 存放图片的时候和我们一般项目中存储的没什么区别
- 如果需要发布组件需要在
podsepc
中添加以下描述,以我的示例工程为例
s.resource_bundles = {
'Demo' => ['Demo/Assets/Demo.xcassets']
}
- 代码获取图片我写了个工具类,就是获取
bundle
之后再获取里面的图片,使用方法也在里面了,使用这种方法Podfile
需要去掉里面默认添加的use_frameworks!
,后续swift再作兼容
//
// ResourceManager.h
// AssetsKit
//
// Created by GuoMS on 2019/2/18.
//
#import <Foundation/Foundation.h>
/* 使用方法,新建一个文件,头文件写入以下宏定义
#import "ResourceManager.h"
//自定义特定的名称
#undef XXXBundle
#define XXXBundle [ResourceManager resourceBundleForClass:[self class] podName:@"组件名称"]
#undef BXXXImage
#define BXXXImage(name) [ResourceManager imageName:name inBundle:XXXBundle]
*/
@interface BQSResourceManager : NSObject
/**
获取组件的bundle并缓存
@param aClass 当前调用的类,用于定位bundle位置
@param name 组件的名字
@return bundle
*/
+ (NSBundle *)resourceBundleForClass:(Class)aClass
podName:(NSString *)name;
/**
制定bundle获取图片
@param name 图片名字
@param bundle bundle实例
@return 图片、为空返回nil
*/
+ (UIImage *)imageName:(NSString *)name
inBundle:(NSBundle *)bundle;
@end
//
// ResourceManager.m
// AssetsKit
//
// Created by GuoMS on 2019/2/18.
//
#import "ResourceManager.h"
@interface BQSResourceManager()
@property (strong, nonatomic) NSMutableDictionary *bundleDic;
@end
@implementation ResourceManager
+ (instancetype)sharedInstance {
static BQSResourceManager *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc]init];
manager.bundleDic = [NSMutableDictionary dictionary];
});
return manager;
}
+ (NSBundle *)resourceBundleForClass:(Class)aClass podName:(NSString *)name {
NSAssert(aClass, @"class 不能为空");
NSAssert(name.length > 0, @"组件名称不能为空");
if (name.length <= 0 || !aClass) {
return nil;
}
//获取bundle
NSBundle *cacheBundle = [[BQSResourceManager sharedInstance].bundleDic objectForKey:name];
if (cacheBundle) {
return cacheBundle;
}
NSBundle *bundle = [NSBundle bundleForClass:aClass];
if (bundle) {
NSString *resourceBundlePath = [bundle pathForResource:name ofType:@"bundle"];
if (resourceBundlePath && [[NSFileManager defaultManager] fileExistsAtPath:resourceBundlePath]) {
bundle = [NSBundle bundleWithPath:resourceBundlePath];
}
[[BQSResourceManager sharedInstance].bundleDic setObject:bundle forKey:name];
return bundle;
}
return nil;
}
+ (UIImage *)imageName:(NSString *)name
inBundle:(NSBundle *)bundle {
NSAssert(bundle, @"bundle 不能为空");
NSAssert(name.length > 0, @"图片名称不能为空");
if (name.length <= 0 || !bundle) {
return [UIImage new];
}
UIImage * image = [UIImage imageNamed:name
inBundle:bundle
compatibleWithTraitCollection:nil];
return image;
}
@end
最后添加了新的头文件之后有时候在Example
工程中导入会提示找不到头文件,可以重新执行pod install
就可以找到了
如果你有遇到什么问题欢迎在评论中回复,我看到的都会回