【iOS】MVP模式

【iOS】MVP模式

文章目录

前言

笔者在之前的iOS开发中学习了MVC架构,最近偶然看到了有关于MVP的内容,下面是笔者对于这部分的内容的一个个人理解。如有纰漏请,还请不吝赐教。

起源

首先我们先来回忆一下我们之前学习的MVC模式:

我们之前学习的经典的MVC模式有很多的优点:

  • 代码清晰,职责分明,易于维护。
  • 代码复用性高,模型和视图可以在多个控制器中重复使用

但是如果随着业务的增加,代码量和复杂程度都会随之提升,MVC的缺点也就暴露了出来:

  • C层很容易就过于臃肿,逻辑代码和业务代码难以分离。
  • 视图和模型的交互逻辑难以在多个视图控制器中进行共享和复用
  • 难以进行单元测试,以为控制器依赖于视图和模型

MVP 架构模式的诞生正是为了解决这个问题。MVP 架构模式将应用程序分成三个主要部分:模型(Model)、视图(View)和表示器或者叫模型视图协调器(Presenter)。这种架构模式使开发者可以更好地管理代码,提高应用程序的可维护性和可扩展性。

各个层的职能

Model

这里的Model层主要负责处理应用程序的数据,包括数据的获取,存储和处理等。

View

这里我们可以发现View变成了Passive View,这里不难发现这里的Passive其实包括了ViewController这个部分的内容,这里的VIew比原先的View多了一层与用户交互的功能。

Present

这个层级可以说是我们整个MVP架构中最重要的一个组成部分,Present层是Model和View之间的一个桥梁,它让Model和View完全独立开来,在MVC中C层的业务代码很大一部分由MVP层中的P层来完成,让我们的ViewController能够更加专注的完成展示UI,处理用户的一个交互。

业务代码

1. 数据处理:我们就以一个简单的登陆注册界面为例子,我们之前写过的知乎日报的为例。知乎日报首页的内容是不是包括了一个从Model层获取我们的一个最新新闻数据的内容,然后我们需要按照时间顺序让其在View层展示,这里原先的内容是在Model层去实现的,而现在转化的了我们的Present层

2.业务流程:根据用户的交互或者其他条件,触发一个不同的业务逻辑,就好比我们知乎日报首页的一个下滑刷新一样,这个内容也应该在我们的一个VC层中去实现的,但是这里我们将他转交到了我们的一个Present层中去实现。

3. 错误处理:处理业务逻辑中出现的一个异常,例如网络连接失败,数据格式错误之类的。

这里面说到的内容我们在MVP中都是通过Present层去实现的。

MVP的一些规范

这里提供一种目前比较多人使用的规范:

  • View层是由UIViewControllerUIView共同组成;
  • View层将委托Presenter层对它自己的操作;
  • Presenter层拥有对View层交互的逻辑;
  • Presenter层跟Model层通信,并将数据转化成对适应UI的数据并更新View
  • Presenter不需要依赖UIKit
  • View层是单一,因为它是被动接受命令,没有主动能力。

来源自:
iOS 架构设计代码实例学习-MVP 模式

一个简单例子

Model层

model层的内容,同MVC大致相似,也是获取一些简单数据的内容。

objc 复制代码
NS_ASSUME_NONNULL_BEGIN

@interface MainPageModel : NSObject
@property (nonatomic, copy) NSString* textString;
@property (nonatomic, copy) NSString* imageString;
@end

NS_ASSUME_NONNULL_END

Present层

这个层是负责实现UIViewController和Model层的一个通信的内容。

objc 复制代码
@interface MainPagePresent : NSObject <PresentProtocol>
@property (nonatomic, weak) id<ViewProtocol> delegate; //这里其实持有的是一个View层的内容
@property (nonatomic, copy) NSArray<MainPageModel*> *model; // 这里其实可以持有一个Service层的引用,通过Service层来获取我们的一个数据层,这里可能会和其他人的代码有些出入
-(void)fetchModel;
- (MainPageData *)dataForIndex:(NSInteger)index; //给主函数的View层传输所有需要的一个内容。实现与Model层的一个通信
@end

Present层对应的协议:

objc 复制代码
@protocol PresentProtocol <NSObject>
-(void)fetchModel;//定义获取数据的内容,这部分内容还可以提取出一个Service层,然后让Service层来实现对应的获取Model层的一个内容
@end

这里我们来简单看一下实现部分:

objc 复制代码
- (void)fetchModel {
    self.model = @[[[MainPageModel alloc] initWithImageString:@"3.jpg" andText:@"照片1"], [[MainPageModel alloc] initWithImageString:@"4.jpg" andText:@"照片2"], [[MainPageModel alloc] initWithImageString:@"5.jpg" andText:@"照片3"]];
    if (self.delegate && [self.delegate respondsToSelector:@selector(reloadCollectionView)]) {
        [self.delegate reloadCollectionView]; //获取数据后开始加载数据内容
    }
}

View层

这个层主要负责一个布局和处理简单逻辑的功能:

objc 复制代码
@interface MainPageView : UIView
@property (nonatomic, strong) UICollectionView* collectionView;
@end

@interface MainPageViewController : UIViewController<UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, ViewProtocol>
@property (nonatomic, strong) MainPageView* iView;
@property (nonatomic, strong) MainPagePresent* present;
@end

这里还有一个View层的协议,设置对应View从Present层获得数据的内容,以及和Present可以调用View的一些公共接口

objc 复制代码
@protocol ViewProtocol <NSObject>
-(void)reloadCollectionView;
@end

有关于UICollectionView的一个设置部分

objc 复制代码
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 11;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    MainPageCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier: @"UICollectionViewCell" forIndexPath: indexPath];
    MainPageData* data = [self.present dataForIndex:indexPath.item]; //这部分内容是一个获取对应的对应的Model层的数据的内容
    cell.imageView.image = [UIImage imageNamed:data.imageName];
    cell.textView.text = data.text;
    return cell;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

界面跳转

根据MVP 模式的设计思路,Presenter 应该只关心业务逻辑的实现,不直接操作View 和进行界面跳转等视图层操作。因此,当需要进行界面跳转时,Presenter 应该将跳转的请求传递给View,由View 负责进行具体的跳转操作。

在这个过程中,Presenter 只需要关心跳转请求的结果是否符合业务逻辑即可。

而跳转后的界面对应的Presenter 可以在界面初始化时由View创建并绑定,与之前的Presenter 进行解绑。所以,界面间通信应该是Presenter 与View 的通信,而不是Presenter 与Presenter 的通信。

优缺点

MVP 的优点:

  • 代码更加模块化,易于维护和扩展。
  • 视图和模型之间的交互逻辑通过Presenter 进行协调,逻辑更加清晰。
  • Presenter 可以通过接口来实现,使得测试更加容易。

但同时,MVP 模式也有不尽人意的地方:

  • Presenter 层会增加代码量,增加了开发时间和成本。
  • 对于小型应用程序来说,MVP 模式可能会显得过于繁琐。
  • Presenter 和View 之间的接口设计可能会变得复杂,需要额外的注意。

小结

这里我们就可以简单实现一个有关于MVP的一个内容,这里也是笔者自己对于MVP这种模式的一个个人理解,之后还会继续学习有关于MVP和MVVM的内容,这里如果有什么问题还请不吝指出。

参考博客:iOS 架构设计代码实例学习-MVP 模式

相关推荐
hxx2211 小时前
iOS swift开发系列--如何给swiftui内容视图添加背景图片显示
ios·swiftui·swift
Magnetic_h5 小时前
【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数(四)
笔记·学习·ios·objective-c
名字不要太长 像我这样就好8 小时前
【iOS】OC语法知识小结
ios·cocoa·xcode
胖虎117 小时前
SwiftUI - (十九)组合视图
ios·swiftui·swift·组合视图
davidson14711 天前
Xcode
ios·swiftui·xcode·swift·apple
weixin_439738481 天前
IOS通过WDA自动化中遇到的问题
运维·ios·自动化
あjdc1 天前
iPhone所有机型的分辨率
开发语言·ios·objective-c·cocoa·iphone
davidson14711 天前
阿里云OSS下载-swift
阿里云·ios·云计算·iphone·swift
福大大架构师每日一题1 天前
35.4 thanos-query 源码阅读
java·spring·ios·prometheus