开发者社区> 6yckvs2xpiv2e> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

iOS项目组件化

简介: 随着公司业务的不断发展,团队不断壮大的同时,项目也随之臃肿起来,如何保障团队协作的高效,自然的想到了组件化这个话题。下面总结下本人的梳理和思考。
+关注继续查看

前言

随着公司业务的不断发展,团队不断壮大的同时,项目也随之臃肿起来,如何保障团队协作的高效,自然的想到了组件化这个话题。下面总结下本人的梳理和思考。

组件化

  • 为什么我们需要组件化 项目模块间的解耦、模块实现可重用、提升团队成员之间团队之间的协作开发效率、更方便单元测试。
  • 并不是所有的项目都适合组件化 如果你的项目较小,模块之间交互简单,耦合很少;模块没有被外部模块引用,只是一个单独的小模块;模块不需要重用,代码也很少被修改;团队规模很小。那么,你对项目就没有必要做组件化。

如果你的项目有以下三个特征以上,就要考虑下进行组件化了:

  1. 模块逻辑复杂,多个模块之间频繁互相引用
  2. 项目规模逐渐变大修改代码变的越来越困难(这里可以理解为:修改一处代码,需要同时修改其他多个地方);
  3. 团队人数变多,提交的代码经常和其他成员冲突
  4. 项目编译耗时较长
  5. 模块的单元测试经常由于其他模块的修改失败
  • 组件化的8条指标

一个项目经过组件化后如何来评判项目组件化是否彻底或者说是否优秀,可以通过以下几个方面:

  1. 模块之间没有耦合,模块内部的修改不影响其他模块;
  2. 模块可以单独编译
  3. 模块间数据传递明确
  4. 模块可以随时被另一个提供了相同功能的模块替换
  5. 模块对外接口清晰且易维护;
  6. 模块接口改变时,此模块的外部代码能够被高效重构
  7. 尽量用最少的修改和代码,让现有的项目实现模块化;
  8. 支持OC和Swift,以及混编。

前4条主要用于衡量一个模块是否真正解耦后4条主要用于衡量在项目实践中的易用程度

组件化分层

一般一个项目主要分为三层:业务层、通用层、基础层

image-20221010183722274.png

组件化封层之后,需要遵循一下原则:

  1. 只能 上层对下层 依赖, 不能 下层对上层 依赖(下层是对上层的抽象);
  2. 项目公共代码资源下沉;
  3. 横向的依赖尽量少有,最好下称到通用模块或者基础模块。

cocoapods组件化

1.创建远程私仓

  • 从git等代码托管平台或者公司的git仓库创建远程代码仓库
  • 本地仓库和远程仓库关联,并作为组件化工程目录。
    建议使用公司的git仓库,可以公开给需要的人员使用,也避免代码泄露问题。
    具体操作参考git的使用

2.创建组件模块工程

打开终端,cd到工程目录下执行命令:pod lib creat 组件名

如我的组件名称为:component-test, 命令:pod lib create component-test

image-20221010195132961.png

创建完成工程的目录如下:

image-20221010203703371.png

编译成功之后,就可以把自己整理的组件化相关的代码拖入到对应的目录Classes下

路径如下:

image-20221010204241595.png

测试组件化代码如下

IWComponent.h文件如下
#ifndef IWComponent_h
#define IWComponent_h
#import "IWNStringRegex.h"
#endif /* IWComponent_h */
IWNStringRegex.h文件如下
#import 
NS_ASSUME_NONNULL_BEGIN
@interface IWNStringRegex : NSObject
+ (BOOL)isValidEmail:(NSString *)email;
@end
NS_ASSUME_NONNULL_END
IWNStringRegex.m文件如下
#import "IWNStringRegex.h"
@implementation IWNStringRegex
+ (BOOL)isValidEmail:(NSString *)email
{
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:email];
}
@end

3.使用示例应用程序测试组件功能

  • Classes 中的文件修改后,打开终端cd到Example下进行 pod install (刚才添加到 Classes 中的文件夹 pod 进来)

image-20221010201904673.png

  • 引入头文件,使用相应的功能
#import "IWViewController.h"
#import "IWComponent.h"
@interface IWViewController ()
@end
@implementation IWViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
    
    NSString * email = @"fan@iw.com";
    BOOL isEmail = [IWNStringRegex isValidEmail:email];
    NSLog(@"是否是邮箱:%d", isEmail);
    
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
  • 测试结果:
2022-10-10 20:50:29.628168+0800 component-test_Example[1448:25782] 是否是邮箱:1

4.修改 podspec 文件

  • 编译示例应用工程,测试组件通过,开始修改 podspec 文件。

一般修改一下几个内容:

  1. 修改版本号
  2. 修改项目的简单概述和详细概述
  3. 修改 homepage 和 source 地址
  4. 添加依赖库

podspec常用字段含义和修改如下

#
# Be sure to run `pod lib lint component-test.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
  s.name             = 'component-test'
  s.version          = '0.1.0'
  s.summary          = '组件的简介'
# This description is used to generate tags and improve search results.
#   * Think: What does it do? Why did you write it? What is the focus?
#   * Try to keep it short, snappy and to the point.
#   * Write the description between the DESC delimiters below.
#   * Finally, don't worry about the indent, CocoaPods strips it!
  s.description      = <<-DESC
  组件的详细描述
                       DESC
# s.homepage 作者主页地址
  s.homepage         = 'https://gitee.com/taijuios'
  # s.screenshots     = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  #license 开源协议
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  # author 作者信息
  s.author           = { 'wangtaiju' => 'wang.taiju@iwhalecloud.com' }
  # source 组件地址,需要组件的git远程仓库地址一致
  s.source           = { :git => 'git@gitee.com:taijuios/component-test.git', :tag => s.version.to_s }
  # s.social_media_url = 'https://twitter.com/'
  # ios.deployment_target 平台和运行最低系统
  s.ios.deployment_target = '10.0'
  # source_files 组件源代码路径
  s.source_files = 'component-test/Classes/**/*'
  
  # resource_bundles 组件所需资源路径,如图片
  # s.resource_bundles = {
  #   'component-test' => ['component-test/Assets/*.png']
  # }
  # public_header_files 对外公开的头文件
   s.public_header_files = 'Pod/Classes/IWComponent.h'
  # s.frameworks = 'UIKit', 'MapKit'
  # dependency 依赖的第三方库
  # s.dependency 'AFNetworking', '~> 2.3'
end

具体语法参考pod官方:https://guides.cocoapods.org/syntax/podspec.html

5.验证podspec文件

编译通过后,终端cd到组件应用根目录, 提交代码到远程仓库,并打tag

git add .
git commit -m "description"
git push origin master
git tag 版本号 (注:这里的版本号必须和 podspec 里写的版本号一致)
git push --tags

执行一下命令:

pod spec lint --verbose --allow-warnings --use-libraries

备注:如果远程仓库和podspec文件中的source地址不一致会报错,远程仓库先打tag,tag需要和podspec文件version一致,否则也会报错不通过。

编译常用的一些命令如下:可以根据需求来选择

--use-libraries 开启库编译

--allow-warnings 允许告警

--sources=3rdlib 第三方依赖

--skip-import-validation 跳过验证

--skip-tests 跳过测试

--verbose 输出日志,

终端显示:component-test.podspec passed validation. 表示成功。

6.提交podspec文件索引

  • 添加pod repo
    pod repo add 'repo名称' 远程仓库地址
pod repo add gitee git@gitee.com:taijuios/component-test.git
  • 验证并提交podspec到远程仓库
pod repo push gitee component-test.podspec --verbose --allow-warnings --use-libraries
  • 备注:pod repo 都远程仓库和podspec文件source需要一致。
    完成后可以在本地cocoapods中看到版本索引了
    image-20221011114036776.png

7.测试

  • 新建一个pod管理应用工程
  • Podfile指定组件源和tag
pod 'component-test', :git => 'git@gitee.com:taijuios/component-test.git', :tag => '0.1.0'
  • pod install,并正常使用则成功。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
开源 iOS 项目分类索引大全
mattt大神的发布程序:https://github.com/nomad/shenzhen ----------------Mac完整项目----------电台:https://github.com/myoula/sostart----------------iOS完整项目----------------1,豆瓣相册 https://github.com/TonnyTao/Do
5412 0
iOS开发UI篇—CAlayer(创建图层)
iOS开发UI篇—CAlayer(创建图层) 一、添加一个图层 添加图层的步骤: 1.创建layer 2.设置layer的属性(设置了颜色,bounds才能显示出来) 3.将layer添加到界面上(控制器view的layer上)  1 // 2 // YYViewController.
738 0
iOS开发UI篇—CAlayer层的属性
iOS开发UI篇—CAlayer层的属性 一、position和anchorPoint 1.简单介绍 CALayer有2个非常重要的属性:position和anchorPoint @property CGPoint position; 用来设置CALayer在父层中的位置 以父层的左上角...
830 0
iOS开发UI篇—CAlayer(自定义layer)
iOS开发UI篇—CAlayer(自定义layer) 一、第一种方式 1.简单说明 以前想要在view中画东西,需要自定义view,创建一个类与之关联,让这个类继承自UIView,然后重写它的DrawRect:方法,然后在该方法中画图。
801 0
iOS开发UI篇—核心动画简介
iOS开发UI篇—核心动画简介 一、简单介绍 Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
884 0
iOS开发UI篇—核心动画(基础动画)
iOS开发UI篇—核心动画(基础动画) 一、简单介绍 CAPropertyAnimation的子类 属性解析: fromValue:keyPath相应属性的初始值 toValue:keyPath相应属性的结束值 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue 如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。
610 0
iOS开发UI篇—核心动画(关键帧动画)
iOS开发UI篇—核心动画(关键帧动画) 一、简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值 属性解析: values:就是上述的NSArray对象。
662 0
iOS开发UI篇—CAlayer简介
iOS开发UI篇—CALayer简介   一、简单介绍 在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。
654 0
iOS开发UI篇—Quartz2D使用(信纸条纹)
iOS开发UI篇—Quartz2D使用(信纸条纹) 一、前导程序 新建一个项目,在主控制器文件中实现以下几行代码,就能轻松的完成图片在视图中的平铺。 1 #import "YYViewController.
655 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
React-Native 在iOS上的性能优化方案
立即下载
loTCandyJar:Towards an Intelli
立即下载
聚划算iOS平台动态化方案LuaView
立即下载