iOS之组件化学习(一)---Git、CocoaPods的简单介绍

前言

一个项目做大了,项目会很大,大家都去编译同一套代码,编译时间过长;
多人开发容易冲突;
更要命的是,修改一个地方,会牵扯到很多地方的修改,也就是项目耦合性太高。
为了解决这些问题,组件化不失为一种好的办法。

在学习之前,先抛几个问题,等学完后,看看自己能否解答
如何划分组件?
如何组织组件?
组件内部资源的使用?
组件间如何通讯?
如何通信包括:跳转、跳转的带参;事件传递

如果你跟我一样,充满好奇,我们一起来学习吧


Git的简单使用

如何将本地一个项目上传到远程仓库?

cd 项目路径下
git init初始化一个本地仓库;

运行结果:Initialized empty Git repository in /Users/admin/learnFold/studyGit/.git/

.git文件夹以外的被称为:工作区
.git文件夹内部的被称为:代码仓库

其中,代码仓库里面有两个重要的部分:
暂缓区、分支(默认为master主分支)

我们要做的就是,把工作区的内容,上传到master分支,这,就实现了git管理
要实现工作区->master分支的移动,需要借助暂缓区,即:
工作区->暂缓区->master
工作区->暂缓区,借助命令:git add .

注意:add .中间有空格

暂缓区->master,借助命令:git commit

在这里插入图片描述

git status查看当前状态
如果是红色,则是处于工作区
在这里插入图片描述
通过命令git add .可将工作区的内容添加到暂缓区。此时再使用git status查看状态,会显示绿色
在这里插入图片描述
然后,通过命令git commit -m '注释'将暂缓区的内容放到master分支上
提交完毕后,再使用git status,可以看到

On branch master
nothing to commit, working tree clean

在这里插入图片描述
该commit只是提交到本地代码仓库里面
想要提交到网络仓库还需要:
git remote add origin 远程仓库地址
git push origin master(分支)

除此之外,可能你还需要了解下如何打标签
git tag -a '0.0.1' -m '注释'或者git tag '0.0.2'
git tag查看
git push --tags将本地所有标签同步到网络库

git tag -d 0.1.0删除标签
git push origin :0.1.0删除远程标签

更多学习可参考:
学习Git小笔记


CocoaPods的简单介绍

CocoaPods官网
首先,需要知道的是:git、svn都是版本管理工具
cocoapods是管理第三方库的一个工具
因此,不要混淆git与cocoapods

pod search AFNetworking搜索AFNetwork框架
pod init初始化一个pod。
工程文件下会生成一个Podfile文件:

# platform :ios, '9.0'
target 'studyGit' do
  use_frameworks!
  pod 'AFNetworking'
end

里面,#是注释

pod install安装即可

pod install
Analyzing dependencies
Downloading dependencies
Installing AFNetworking (4.0.1)

成功之后,可以看到项目工程里面多了两个文件:
Podfile.lock以及xxx.xcworkspace

好了,项目已经引入了CocoaPods管理了

在git管理的时候,不需要上传Pods文件

有些命令不知怎么使用,请使用pod --help

问:pod install与pod update的区别?

pod install第一次是按照Podfile里面的配置进行安装配置
以后,pod install是按照Podfile.lock里面的配置进行安装配置

pod update是每次都是按照Podfile里面的配置进行安装配置,然后更新Podfile.lock

问题就在于,如果没有指定版本号,pod update就是按照引入第三方库的最新版本进行更新的。

这样,有可能你更新了最新的库,而你的小伙伴还是使用老的库,造成某些问题
解决的话也简单,你pod update上传代码后,下次你的小伙伴拉代码,需要执行下pod instal即可

+install Install project dependencies according to versions from a
Podfile.lock
+update Update outdated project dependencies and create new Podfile.lock

问:Podfile与Podfile.lock的区别?


讲解完cocoaPods的使用,我们来了解下cocoaPods是如何工作的,或者说cocoaPods的机制是怎样的,怎么就可以实现第三方库的管理呢?

cocoaPods的机制

废话不多说,直接上小码哥的图:
在这里插入图片描述

当我们pod search x第三方库的时候,是在本地库里面的某一个包含key-value的文件中查找对应的三方库,找到之后,在.spec描述信息里面,找到第三方库的远程仓库地址,然后进行下载。

也就是,在远程索引库中,存放的是第三方库的.spec描述信息,根据描述信息,找到真正的第三方库的远程地址

了解了CocoaPods的机制后,想不想知道:
你,如何将一个自己写的三方库也放入到CocoaPods里面进行管理,让后人敬仰呢?
其实,步骤很简单,分为三步:(打开冰箱🚪,🐘进去,关🚪)
第一步:自己写好源码,并上传到远程仓库
第二步:写一个.spec描述文件
第三步:将.spec描述文件上传到远程索引库

在https://github.com/CocoaPods/Specs/tree/master/Specs
随便打开一个文件,可看到:
.json该git地址,就是该第三方库的项目下载地址

问:本地索引库在哪里呢?

/Users/admin/.cocoapods/repos/trunk/Specs

第一步:创建代码并上传到Git仓库,就不做叙述了

第二步:写一个.spec描述文件
使用pod spec create testLib命令,可以看到,多了一个testLib.podspec文件
该文件就是.spec描述文件
具体.spec文件里面怎么写,或者说怎么读,可以参考:cocoapods官网下面的podspec

例如:

Pod::Spec.new do |spec|
  spec.name         = 'Reachability'
  spec.version      = '3.1.0'
  spec.license      = { :type => 'BSD' }
  spec.homepage     = 'https://github.com/tonymillion/Reachability'
  spec.authors      = { 'Tony Million' => 'tonymillion@gmail.com' }
  spec.summary      = 'ARC and GCD Compatible Reachability Class for iOS and OS X.'
  spec.source       = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0' }
  spec.source_files = 'Reachability.{h,m}'
  spec.framework    = 'SystemConfiguration'
end

最重要的就是,将远程Git代码地址放在homepage后:
spec.homepage = "https://github.com/x/testlib"
将代码clong地址放在source后
spec.source = { :git => "https://github.com/x/testlib.git", :tag => "#{spec.version}" }
tag标签要打,不然不知道你要上传的是哪个版本
其实也很容易理解,你下载的AFN不都有版本么,没有版本不乱套了

.spec里面有一个spec.source_files = "Classes", "Classes/**/*.{h,m}"
这个是干嘛的呢?
首先,你在某一个git项目中,可以看到某个项目中还包含一些example的文件
但,在你pod install使用这个第三方库的时候,你是不需要这些example文件的
所以,你需要把你将提供给别人下载使用的文件放在source_files里面,别人只下载这里面的文件就可以满足功能了

此外
spec.description = "描述是空的不行"

第三步:将.spec描述文件上传到远程索引库
上传的话,使用的是trunk上传
官网上有一些介绍

首先,要注册trunk
pod trunk register 123@qq.com 'name'
spec.license = "MIT"

在这里插入图片描述
使用命令pod trunk push testLib.podspec上传.spec文件
然后经过审核,就可以了

完成之后,有可能pod search 自己的库名还是找不到自己的库
这是因为,远方的库更新了,你自己的seach缓存没有更新,因此,你需要把自己的缓存文件删除,重写下载即可。
本地search缓存路径为:/Users/admin/Library/Caches/CocoaPods/search_index.json


组件化

概念

将一个单一工程的项目,分解为各个独立的组件;
然后按照某种方式,任意组织成一个拥有完整业务逻辑的工程

一般来说,可以分为基础组件、功能组件、业务组件

基础组件

包括:
基本配置:常量、宏
分类
网络:AFN、SDWebImage
工具:日期时间处理、文件处理、设备信息等

功能组件

包括:控件、功能
比如:拍摄视频、照片,就可以封装成一个拍摄视频、照片的组件。在组件内部实现拍摄、添加滤镜、选择照片库等等一系列操作
又比如:下载功能也可以封装成一个单独的下载功能组件

业务组件

业务组件可以是首页、个人中心、或者相亲项目、购买、打车等等某一个模块做为一个业务组件
相亲与打车、或者买东西解耦,不做关联,这样,就可以改动相亲里面的代码,不至于影响打车项目

三者的关系大致为:
在这里插入图片描述

业务组件在最上层
业务组件依赖于基础组件、功能组件
业务组件之间,以及功能组件之间,不能产生相互依赖


组件间通信

组件化之间通信大致有三种方法:

  1. URL 路由
  2. Target - Action
  3. Protocol - Class

1. URL路由

注册模块

register url 注册模块
通过 url 绑定 一个 操作绑定Block
url格式 = 协议头://模块/参数列表

打开模块

open url 打开模块

其代表是MGJRoute
控制器不作为中间件,使用MGJRoute作为中间件。每个组件里面都需要注册MGJRoute。MGJRoute里面存的是key-url,通过注册的URL做跳转
优点:

  • 技术比较成熟
  • 解决了跨端上的差异性,同一个路由iOS和Android都可以使用

缺点:

  • 每个组件都需要初始化,内存里需要维护url-block映射表,组件多了会有内存问题(注册方法是在+load方法被调用)
  • 需要去注册和维护路由表

在这里插入图片描述

2. Target - Action

目标-行为

基于Runtime+OC反射机制+分类

在Object-C中Target就是消息接收者对象,Action就是消息
比如我们要调用Person对象的play方法我们会说向Person对象发送了一个play消息,此时Target就是person对象,Action就是play这个方法

之前我们在AViewController中push到BViewController,需要在AViewController类文件中import进BViewController,这样二者就会产生耦合,现在利用Target-Action机制,我们不再直接import进BViewController,而是利用NSClassFromString(<#NSString * _Nonnull aClassName#>)这个api将BViewController这个字符串反射成BViewController这个类,这样我们就可以根据反射后的类进行实例化,再调用实例化对象的各种方法。

利用Target-Action机制,我们可以实现各种灵活的解耦,将任意类的实例化过程封装到任意一个Target类中,同时,相比于URL Router,Target-Action也不需要注册和内存占用,但缺点是:编译阶段无法发现潜在的BUG,而且,开发者所创建的类和定义的方法必须要遵守Target-Action的命名规则,调用者可能会因为硬编码问题导致调用失败。

这种方案对应的开源框架是:CTMediator和阿里BeeHive中的Router,二者都是通过反射机制拿到最终的目标类和所需要调用的方法(对应的api是NSSelectorFromString(<#NSString * _Nonnull aSelectorName#>)),最终通过runtime或performSelector:执行target的action,在action中进行类的实例化操作,根据具体的使用场景来决定是否将实例对象作为当前action的返回值。

通过NSClassFromString获取类并创建实例
通过performSelector + NSInvocation动态调用方法

3. Protocol - Class

和Targer Action有点像, 只不过具体功能的声明是写到一个协议里, 开发者A只需要从Mediator获取到实现了某个Protocol的类, 执行其中的方法即可

就是通过protocol定义服务接口
组件通过protocol接口,来访问实现接口的模块定义的服务:

具体实现就是把protocol和class做一个映射
同时在内存中保存一张映射表
使用的时候,就通过protocol找到对应的class来获取需要的服务。

通过protocol获取真实的class

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值