美文网首页IOS开发
iOS MVC及MVP设计架构浅析及使用实例

iOS MVC及MVP设计架构浅析及使用实例

作者: 吃大米的小蚂蚁 | 来源:发表于2019-06-19 13:12 被阅读0次

本文demo地址:https://github.com/TheRuningAnt/TestMVPFramework.git

虽然做了好几年iOS开发了,洋洋洒洒也写过了很多代码,也解决过一些棘手的需求,但是总是感觉自己写的代码不够简洁,总是感觉逻辑不是很清晰,每天做的工作都只是在不断的搬运以前的东西拿来用,虽然功能都能够实现,但是一旦单个页面业务逻辑过多过复杂(比如一个完整的直播间内容,直播、回放观看及下载、弹幕、举手发言、表情选择、聊天列表、课件演示等等),总是容易写出来长长长长的代码。虽然已经尽最大程度将各个业务进行独立的封装,最大限度的实现代码和方法的复用,但是等项目结束后仍然发现自己写的项目虽然功能正常,却实在过于冗杂,难以维护,简而言之,就是感觉自己写的代码太垃圾!
而且不管大小项目,都会存在这个问题,感觉自己的代码架构不够精简,虽然层级之间已经最大程度解耦,但是单个层级内的逻辑和代码量还是会跟业务复杂度一起直线上升,虽然实现了视图层和模型层的分离,但是往往或多或少仍然存在视图层和数据模型层间直接通讯的情况(例如典型的cell.model = model),实在是看的很难受。一直想好好研究下代码的设计架构,来让自己的代码可读性和可维护性都可以有所长进,但是一直时间不是很充裕(好吧,懒。。。),所以一直没有静下心来好好研究一番,直到又做完一个项目,看着两千多行长长的代码和复杂的业务,陷入了沉思。。。
实在看不下去了,所以写了这篇文章,简单的分析一下这几年时间的累积对传统MVC架构的理解以及对MVP架构的理解和使用示例。

不同的人对同一种架构都会有着自己的理解,所以我只是简单的阐述下根据我自己的经验以及使用的心得来浅浅的聊一下我对这两种架构的领悟,也欢迎围观的大佬和小朋友随时指点。好了,进入正题。
MVC架构的优势和存在的问题
MVC作为传统的设计架构,已经在很多端都有根深蒂固的使用历史了,也是苹果公司一直主推的设计架构,很多iOS开发人员用的最多也最熟悉的也是这种设计架构,感谢伟大的创始人,MVC架构帮助我们建立良好的业务分层意识以及解决了很多很多的需求场景。MVC的核心理念是使用控制层来主导视图层和模型层之间的数据沟通,视图层和模型层不应该有直接的交互,但是开发的过程中偶尔总是会不那么严谨,例如在视图层直接拿来模型层的数据来用啥的,投机取巧是万恶之源,呵。
MVC提出了数据和业务及视图分层的概念,使得我们在代码编写的过程中有意识的进行基本的对网络层、控制层、视图层和模型层进行分层解耦处理,但是随着设备的发展及人们生活需求的提高,手机端的业务也越来越复杂,控制层一直被我们以万金油的形式来使用,不仅仅被我们拿来处理页面视图层级的控制显示、还担负着处理根据自身生命周期的变动可能触发的业务逻辑、数据的部分解析处理、各种系统组件和我们自定义的代理以及他们的响应、定义的一堆属性,以及他本身的主要工作:处理视图层用户产生的交互对模型数据进行读写,并且同步反馈给视图层进行显示刷新,可能Controller心里一万头MMP但是并不想说什么,只是越来越不想被我们那么轻易的梳理清楚自己写的业务逻辑,时间长了也越来越变得难以维护,尤其是过了一个月之后,产品突然想:哎,那个啥,改一下。然后我们打开代码,一看2000+的controller。。。

所以,MVC虽然经典,但是遇到一些比较复杂的业务场景,很容易造成控制层的臃肿和厚重,变得难以梳理和维护,还是要好好考虑一下如何给控制层减压及想办法抽取出来更多的内容单独处理,比如使用MVP的架构模式。
MVP
MVP被很多人解析为Model-View-Presenter,其实在我看来,MVP也是从MVC的基础上衍生而来,主要还是一个面向协议的编程模式。模型层跟MVC里的模型层一致,处于一个数据模型建立以及数据处理的层级,但是视图层就不会是单纯的指一些基本视图了,controller的视图也应该归纳在视图层。而我们自定义的Presenter则担任起了绝大部分可以抽离出来的业务逻辑,controller只是控制简单的视图层级控制以及presenter的调度使用。presenter处理数据在模型层和视图层的流通,模型层和视图层不允许有任何直接交互。presenter和Controller通过代理的方式进行互相调用,视图层和presenter也可以通过代理或者直接交互的方式进行数据流通,模型层对数据的更改和页面的更新必须通过presenter来在页面上进行展示。所以我们需要再配套一个协议文件以及独立的网络层来保证一个完整严谨的MVP架构模式。话不多说,下面是我自己写的一个MVP实例文件
效果


gif.gif

文件夹结构。


屏幕快照 2019-06-19 02.10.51.png
其中
service负责模拟一个异步的网络数据请求
presenter则是作为主要的业务处理层级
controller负责presenter的创建和调度使用
view负责视图及数据的更新展示

model负责数据的处理及作为数据的模型
TestPresenterProtocol 声明页面直接调用需要的代理方法,控制页面直接交互的接口
该demo的基本功能是模拟数据加载,加载之后tableView里进行展示,可以通过cell里的加减数值按钮修改对应的展示内容,下拉刷新之后页面数据重新加载回归原始状态。
经过抽离之后,controller里的基本的代码量如下:


屏幕快照 2019-06-19 02.29.47.png
就已经实现了我们的业务需求。后来为了演示controller与presenter之间通过协议的互相调用,又添加了加载提示视图的显示和隐藏功能。这个代码量跟我们之前实现同样需求的controller相比,已经大大减少了很多吧。其实一开始想将tableView也直接放在presenter里创建,controller使用的时候只需要直接从presenter里获取就好,这样代码量将减少到30行左右。后来考虑了一下,盲目为了代码精简而进行过度抽取分离反而得不偿失,tableView作为视图还是应该在controller里创建,presenter可以引用处理其逻辑,但是不应该负责它的创建和加载以及生命周期,应该专注于业务逻辑的处理,所以还是拿回controller里。
简单描述一下各个文件里的主要内容:
Service:
模拟网络请求,只是一个简单的数据加载,代码寥寥几行
屏幕快照 2019-06-19 02.34.12.png
TestPresenter里进行了控制器和视图组件的绑定以及网络数据的加载
屏幕快照 2019-06-19 02.35.37.png
处理tableView的代理逻辑和cell中的点击事件处理逻辑
屏幕快照 2019-06-19 02.40.22.png
以及给tableView添加下拉刷新等操作。
不过要注意presenter对controller及其中的视图引用都为弱引用,避免循环引用的产生。

controller则负责presenter的创建、调用及实现代理协议中定义的方法


屏幕快照 2019-06-19 02.42.15.png

TestCell 视图层负责接收用户的交互事件并且通过代理反馈给presenter进行处理以及数据的同步


屏幕快照 2019-06-19 02.43.21.png
还有我们的代理文件里的定义
TestPresenterProtocol 定义了cell的点击代理以及controller展示/隐藏提示视图的代理
屏幕快照 2019-06-19 02.44.47.png

这样,我们就以MVP架构实现了这样一个简单的需求。如果presenter里的业务量比较繁杂,我们可以将整个业务分为几个小模块,通过创建presenter的category来实现业务的进一步分层解耦,避免presenter文件过于臃肿的情况出现。

总结: 其实在我看来,不同的开发者对于同一种设计架构都有自己的理解,实现的方式也都不尽相同。并不是说对于某种架构就一定有明确的文件夹路径和定死的规范让我们循规蹈矩的来使用,如果一板一眼的按照某种特定的方式来写,那么了解更多的架构模式反而会成为我们开发的累赘。重点是我们在设计自己项目的时候有意识的去使用这种思想来减轻我们的代码冗余量和控制层的厚重程度,让我们的项目变得结构清晰简洁、业务分层明了,便于他人阅读和日后维护。而且合适的架构并不一定意味着代码量的减少,有时候反而代码量和文件数会增加一些。但是采用新的架构的原则一定是这个架构可以让我们的项目结构变得清晰,维护成本大大降低。
完。

相关文章

网友评论

    本文标题:iOS MVC及MVP设计架构浅析及使用实例

    本文链接:https://www.haomeiwen.com/subject/zrbfqctx.html