【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 模式

相关推荐
Digitally4 小时前
如何用4 种可靠的方法更换 iPhone(2025 年指南)
ios·iphone
9765033357 小时前
iOS 审核 cocos 4.3a【苹果机审的“分层阈值”设计】
flutter·游戏·unity·ios
I烟雨云渊T7 小时前
iOS Alamofire库的使用
ios
程序员老刘·8 小时前
iOS 26 beta1 真机无法执行hot reload
flutter·ios·跨平台开发·客户端开发
EndingCoder8 小时前
React Native 构建与打包发布(iOS + Android)
android·react native·ios
程序员小刘8 小时前
HarmonyOS 5鸿蒙多端编译实战:从Android/iOS到HarmonyOS 5 的跨端迁移指南详
android·ios·华为·harmonyos
I烟雨云渊T8 小时前
iOS swiftUI的实用举例
ios·swiftui·swift
getapi10 小时前
将 App 安装到 iPhone 真机上测试
ios·iphone
90后的晨仔1 天前
RxSwift 中的 `Single`:单元素响应式编程简单实践
ios
二流小码农1 天前
鸿蒙开发:CodeGenie万能卡片生成
android·ios·harmonyos