当前位置: 首页 > 编程日记 > 正文

iOS应用模块化的思考及落地方案(二)模块化自动构建工具的使用

1.0 iOS模块化中的问题

前文已经介绍了模块化的流程及一些常见的问题,我们在这里再次总结一下。

在工作中,当我们开始一个新项目的时候,最先考虑的就是模块化工作。

模块化工作的想法是很美好的,可是执行过程中会遇到很多的问题,而这些问题可能会让我们在工作中举步维艰。

  1. 工具使用问题。iOS的模块化一般会使用cocoapods工具,这个工具很强大,内容也很丰富,我们想要完成模块化工作,需要建立私有库,编写podspec文件,处理资源,编写Podfile文件,建立本地依赖等等。让团队成员每个人都精通这个工具是不必要的。因此经常会在使用工具中遇到不易解决的问题,从而浪费大量的时间。

  2. xcode设置问题。xcode设置项多如牛毛,很多内容看起来并不直观,需要我们去查阅官方文档来解决。而且这些设置数量多,使用的频率又少,所以难免会出现这样的情况:每个人都遇到的问题,然后各自去花时间解决,然后过段时间遇到相同的问题常常就忘记了,还要花时间去查阅解决,造成资源的重复浪费。

  3. 模块间依赖的问题,当你依赖的也是私有库的其他模块(下文中称为自有模块)时,开发中可能要同时修改多个模块,这样就会出现在多个工程中切换的问题。

  4. 规范问题,每个人建立模块的方式可能都不同,包括工程结构,工程设置等等。这样一来,不同的模块可能差异特别大,当跨模块开发或者代码交接的时候,可能就会出现难以解决的问题。

  5. 设置的变更修改都是手动修改,有时候难免会因为疏忽,而导致难以发现的错误,当需要处理的模块和依赖较多时,发生错误的概率也会增加。

2.0 编写自动化工具

为了解决这些问题,让团队能够将精力全部集中到业务开发中,特使用bash shell开发一个构建工具,用于自动化处理模块化的过程中遇到的设置及工具使用问题。

工具的地址如下:https://github.com/hardman/AWModularization

使用这个自动化工具你将会获得如下能力:

  1. 一条命令即可创建模块工程,创建.podspec及Podfile文件,自动安装依赖,工程默认使用静态库,支持Swift和OC
  2. 一条命令即可拉取之前开发的模块,并且安装好所有依赖
  3. 一条命令即可自动打tag,自动更新.podspec文件,将工程推送到pod服务器
  4. 自有模块的列表,将会保存在单独git库中,便于有依赖模块时,可动态加载
  5. 自有模块的依赖都通过.podspec文件使用local path的方式安装,这样当被依赖的模块也需要修改时,不需要打开多个工程

因此,使用这个自动化工具,你不需要了解cocoapods工具,也不需要处理任何工程和工具设置,可以将注意力都集中到业务开发中。

【注】工具使用静态库作为模块的输出文件。

3.0 工具的使用

3.1 基本使用步骤

  1. 将工程clone到本地目录
  2. 打开tools/config修改配置文件
    • modulelistgitaddress.txt:新建一个git库,并将地址保存在这个文件中,地址最好是以git@开头。这个git库用于保存所有自有模块名称及地址。
    • podspecsaddr.txt:再新建一个git库,将地址保存在这个文件中,地址最好是git@开头。这个git库就是你的私有库地址。
    • podspecsname.txt:为你的git库取一个名字,保存在这个文件中
    • 上述3个文件都只有一行
    • dependencypodrepos.txt:这个文件保存你的app依赖的其他pod repos,一般情况下保持默认即可,支持多行,每行保存一个地址
    • 由于这些配置几乎不会修改,考虑将这些文件提交到你自己的git库中
  3. 执行 ./create.sh -n=[模块名] -b=[bundle id] -t=[s|f|r] 即可创建工程
    • 脚本执行过程中会要求输入一些工程基本信息及所依赖的模块,请认真输入,不要遗漏
    • 创建的工程会自动打开,并且可以直接执行
    • 创建好的模块文件在:工程根目录/modules
    • 例:./create.sh -n=HelloWorld -b=com.helloworld -t=s
  4. 模块开发完毕,需要将代码提交到develop分支,然后执行./push.sh [模块名] [tag]
    • 执行push.sh时,模块必须在develop分支上
    • 执行成功后,你的模块就已经提交成功,可以通过Podfile文件引用了
    • 例:./push.sh HelloWorld 0.0.1
  5. 使用 ./pull.sh [模块名] 即可下载其他未同步到本地的自有模块
    • 执行成功后,会自动下载所有依赖的模块,并通过local path添加到模块依赖中
    • 例:./pull.sh HelloWorld

3.2 如何提升模块所依赖其他模块的版本号

有的时候,当前模块所依赖的模块版本升级了,需要修改当前模块的依赖文件。
有2种方法:

  1. 直接修改文件
    • 需要修改的文件有2个,一个是文件根目录的dependency.txt文件,文件内记录了当前模块依赖的自有模块
    • dependency.txt文件记录模块版本的格式是:每行一个模块;格式为:模块名@@版本号,版本号支持~>前缀,不可带空格
    • 另一个文件是模块名.podspec文件
    • 按照podspec文件要求的格式去修改版本号
  2. 使用脚本修改
    • 执行命令:./utils.sh [模块名] upgradedependency [依赖的模块名] [版本号]
    • 其中版本号可以为空
    • 例子:./utils.sh LoginModule upgradedependency AFNetworking 3.5.0
    • 例子:./utils.sh LoginModule upgradedependency AFNetworking
  3. 版本号可支持英文字符:a.b.c

3.3 如何在模块工程内使用Swift&OC混编

  1. 在module工程内创建OC的类文件及swift文件,假设OC类名为 TestOC,swift类名为TestSwift
  2. 让OC能够访问Swift类
    • 只需要在TestOC.m中添加import。例:#import "模块名/模块名-Swift.h"
    • 另外需注意的是,TestSwift类必须是public并继承自NSObject。
  3. 让Swift能够访问OC类
    • 在 [模块名].h 这个文件中引入你的头文件。例:#import "TestOC.h"
    • xcode - build phases - [模块名].h 文件必须在public区域

3.4 关于模块资源文件的获取

  1. 由于模块都是静态库,所以最终运行到app中后,每个模块的资源文件(.xcassets, .xib, .png, .jpg, .jpeg, .gif, .txt, .plist, .bundle, .zip, .car)都是放到: "模块名.bundle"文件中的,而这个bundle在main bundle的根目录(这也是要求模块名防止重名的原因之一)
  2. 所以获取图片可以使用 UIImage.init(named: name, in: bundle, compatibleWith: nil) 方法
  3. 获取其他文件也需要指定bundle才可以
  4. 开发过程中,获取任何资源都需要带bundle,不能直接使用类似 UIImage.init(named:String)这种方法,即使是在模块工程内部的代码也不行
  5. 需要注意的是,静态库的单元测试target是无法获取资源的

3.5 注意事项

  1. 模块名要防止重复,不但要防止同一个私有库重复,也要防止与其他pod repo内的模块重复
  2. 依赖库不可产生循环依赖,比如 A依赖B,B依赖C,C依赖A
  3. 每个模块都有一个develop分支,develop分支的代码总是与最新的tag保持一致。执行push命令时,代码总是在develop分支上
  4. 开发期间(集成测试前)总是依赖本地模块,每次总是在集成测试前,才会执行push.sh脚本
  5. 如果当前的开发模块有修改,同时依赖的模块也有修改,则需要先push当前模块所依赖的模块,最后push当前模块。这时候可能需要使用 ./utils.sh [模块名] upgradedependency [依赖的模块名] [版本号] 命令修改模块所依赖的模块的版本号

–完--

  1. iOS应用模块化的思考及落地方案(一)模块的划分及模块化工作流程
  2. iOS应用模块化的思考及落地方案(二)模块化自动构建工具的使用

相关文章:

aws fargate_我如何在AWS Fargate上部署#100DaysOfCloud Twitter Bot

aws fargateAfter passing my last certification, I asked myself how much time I spent studying cloud computing.通过上一份认证后,我问自己自己花了多少时间研究云计算。 More than 100 days!超过100天! It also made me realize two things:这也…

think in Java 第五章之垃圾回收类型

1.引用计数: 每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1,当引用离开作用域或被置为null时,引用计数减1. 缺陷:在对象循环引用时,存在“对象应该被回收,引用计数…

Yii 错误页面处理

【错误页面处理】 訪问一个错误的控制器 訪问一个错误的方法 有些控制器和方法禁止訪问 以上訪问会提示错误信息 404 403 以上错误信息是不方便给外边用户看到的。 1. 安全隐患 2. 用户体验不好 错误信息在site/error这个地方定义的。如今我们要自己定义错误页面来显示我们的错…

设置RGBColor

#define kUIColorFromRGB(rgbValue) [UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

自学成才翁_作为一名自学成才的开发者从“我的旅程”中吸取的教训

自学成才翁The path of the self-taught developer is tough and filled with uncertainty. There is no straight line from newbie to career programmer. Because of this, I believe all self-taught developers have a unique story to tell.自学成才的开发者之路艰难而充…

67)vector的begin() end() 和 front() back()的区别 rbegin() rend()

1) 2)v1.begin() 和v1.end() 是作为迭代器v1的 第一个位置 和 最后一个元素的下一个位置。 v1.front() 是v1这个动态数组的第一个元素的值 v1.back()是v1的最后一个元素的值。 3) 4)正向和反向的使…

倒置函数reverse的用法

倒置字符串函数reverse&#xff1a;用于倒置字符串s中的各个字符的位置&#xff0c;如原来字符串中如果初始值为123456&#xff0c;则通过reverse函数可将其倒置为654321&#xff0c;程序如下&#xff1a;#include<stdio.h>#include<string.h>void reverse(char s[…

设置tabbaritem的title的颜色及按钮图片

设置title颜色&#xff1a; [[UITabBarItem appearance] setTitleTextAttributes:{NSForegroundColorAttributeName : kUIColorFromRGB(0xb2151c)} forState:UIControlStateSelected]; 设置按钮图片&#xff1a; UIImage *commonImage [UIImage imageNamed:[NSString strin…

helm部署仓库中没有的包_Kubernetes的Helm软件包管理器简介

helm部署仓库中没有的包Before we dive into the Helm package manager, Im going to explain some key concepts to deploying any application anywhere. Ill also give you a brief introduction to Kubernetes terminology.在深入研究Helm软件包管理器之前 &#xff0c;我将…

mem 族函数的实现

1.void * memcpy ( void * dest, const void * src, size_t num ); 头文件&#xff1a;#include <string.h>memcpy() 用来复制内存&#xff0c;memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest 所指的内存地址上。memcpy() 并不关心被复制的数据类型&#xff…

快排递归非递归python_Python递归神经网络终极指南

快排递归非递归pythonRecurrent neural networks are deep learning models that are typically used to solve time series problems. They are used in self-driving cars, high-frequency trading algorithms, and other real-world applications.循环神经网络是深度学习模型…

我的hadoop学习之路

Hadoop实现了一个分布式文件系统&#xff08;Hadoop Distributed File System&#xff09;&#xff0c;简称HDFS。HDFS有高容错性的特点&#xff0c;并且设计用来部署在低廉的&#xff08;low-cost&#xff09;硬件上。 Hadoop的框架最核心的设计就是&#xff1a;HDFS和MapRedu…

日期处理工具类 -【二】

1、返回本周的第一天(周日为每周第一天) 1 /**2 * 返回本周的第一天(周日为每周第一天)3 * return4 */5 public static String getTheFirstDayOfThisWeek(){6 SimpleDateFormat format new SimpleDateFormat("yyyy-MM-dd");7 Calendar cal Calendar.get…

超越对手pdf_如何创建一个超越竞争对手的移动应用

超越对手pdfThe amount of time people spend on their mobile phones has increased over the years, and so has the number of people using mobile devices.多年来&#xff0c;人们在手机上花费的时间增加了&#xff0c;使用移动设备的人数也增加了。 It’s safe to say t…

vue路由对象($route)参数简介

路由对象在使用了 vue-router 的应用中&#xff0c;路由对象会被注入每个组件中&#xff0c;赋值为 this.$route &#xff0c;并且当路由切换时&#xff0c;路由对象会被更新。 so , 路由对象暴露了以下属性&#xff1a; 1.$route.path 字符串&#xff0c;等于当前路由对象的路…

join......on 后面的and 和where的区别

a.where 是在两个表join完成后&#xff0c;再附上where条件。   b. and 则是在表连接前过滤A表或B表里面哪些记录符合连接条件&#xff0c;同时会兼顾是left join还是right join。即   假如是左连接的话&#xff0c;如果左边表的某条记录不符合连接条件&#xff0c;那么它不…

block的运用

cell的.h文件 typedef void(^ActivityCellBlock)(NSString *str); interface ActivityCell : UITableViewCell property (nonatomic,strong) NSArray *labelAry; property (nonatomic,copy) ActivityCellBlock myBlock; -(void)showCell:(ActivityCellBlock)myBlock; cel…

如何在Ubuntu 20.04上设置Python虚拟环境

I recently got myself a “new” laptop – a Lenovo x270 (yay)! And once again I needed to set up a Python virtual environment. So of course I Googled for a solution, just to find my previously written article on the same topic!我最近给自己买了一台“新”笔记…

getURLParameters - 网址参数

返回包含当前URL参数的对象。 通过适当的正则表达式&#xff0c;使用 String.match() 来获得所有的键值对&#xff0c; Array.reduce() 来映射和组合成一个单一的对象。 将 location.search 作为参数传递给当前 url。 const getURLParameters url >url.match(/([^?&])…

block的使用

#import "ViewController.h" /* 使用Block最大的一个好处就是可以在代码块中随时访问外部变量 比如你在A.class类中的某个方法中声明了一段代码块.你可以在代码块中直接对A.class所拥有的成员变量进行调用,并且,通过一定的条件(__block),还可以随时的修改这…

关于二级菜单的问题

大家在做二级菜单的时候经常会碰到鼠标移出一级菜单&#xff0c;二级菜单瞬间消失&#xff0c;根本不给你机会移到二级菜单上&#xff0c;今天分享下怎样解决这个问题。 ①第一种介绍一种简单粗暴的方法&#xff0c;二级菜单的元素放入一级菜单中。 代码地址&#xff1a;http:h…

python打印换行符_Python换行符以及如何在不使用换行符的情况下进行Python打印

python打印换行符Welcome! The new line character in Python is used to mark the end of a line and the beginning of a new line. Knowing how to use it is essential if you want to print output to the console and work with files.欢迎&#xff01; Python中的新行字…

tomcat启动后 项目运行缓慢,要几十到几百秒不等 怎么样./startup.sh 运行加快

修改 linux系统中 /usr/local/jdk1.8.0_11/jre/lib/security/java.security 借力 好文章。我们新的Linux系统&#xff0c;部署了多个 Tomca&#xff0c;同时重启后t, 每次都阻塞差不多260秒左右。修改之后总的启动时间下降到6-8秒左右。另外&#xff0c;不确定为什么&#xff0…

转载 C#中使用结构来传递多个参数

C#中当参数超过5个时&#xff0c;建议用结构来传递多个参数。 示例代码如下&#xff1a; 1 public struct MyStruct2 {3 public string str;4 public int number;5 }6 7 class Program8 {9 static void Main(string[] args) 10 { 11 MyStruct myStruct…

xmpp 开源项目选择_如何选择和维护安全的开源项目

xmpp 开源项目选择评估开源项目安全性的一些技巧。 (A few tricks for assessing the security of an open source project.) There is a rather progressive sect of the software development world called the open source community. 在软件开发领域&#xff0c;有一个相当…

【2018-01-22】HTML-表单及表单元素

<body><!--表单--><form action"" method"post"><!--文本类--><input type"text" value"" placeholder"请输入用户名"/><!--文本框--><input type"password" value"…

取消tableView多余的横线

- (void)setExtraCellLineHidden: (UITableView *)tableView{UIView *view [UIView new];view.backgroundColor [UIColor clearColor];[tableView setTableFooterView:view];}

iOS 自定义UITabBar

推荐一篇非常好的集成各种UITabBar的三方库 《点击这里直取demo》 另外一篇根据runtime定制了一款可以出轨的UITarBar 《Runtime实战之定制TabBarItem大小》 点击view的触发机制《iOS事件分发机制&#xff08;一&#xff09; hit-Testing》 摘自&#xff1a; UIView中提供两个…

react入门代码_如何在React中构建温度控制应用程序-包括提示和入门代码

react入门代码我们正在建立的 (What were building) In this beginner React project, were going to learn how to use state hooks, handle events, apply CSS based on state, and more! Check it out: 在这个初学者的React项目中&#xff0c;我们将学习如何使用状态挂钩&am…

决策树(chap3)Machine Learning In Action学习笔记

优点&#xff1a;计算复杂度不高&#xff0c;输出结果易于理解&#xff0c;对中间值的缺失不敏感&#xff0c;可以处理不相关特征数据。缺点&#xff1a;可能会产生过度匹配问题。适用数据类型&#xff1a;数值型&#xff08;必须离散化&#xff09;和标称型。决策树创建分支的…