iOS中MVP架构实践小技巧

栏目: IOS · 发布时间: 5年前

内容简介:一般来说,MVP架构在Andriod中用的比较多,但它也可以在iOS中使用。我在重构项目的一个功能时,为了改善以前代码的层次结构,同时也想体验一下MVP的实践,所以使用了该模式,同时也积累了一点小技巧。MVP分层模型以及交互关系如图所示:view和model通过presenter进行交互,切断直接联系。

一般来说,MVP架构在Andriod中用的比较多,但它也可以在iOS中使用。我在重构项目的一个功能时,为了改善以前代码的层次结构,同时也想体验一下MVP的实践,所以使用了该模式,同时也积累了一点小技巧。

MVP分层模型以及交互关系如图所示:

iOS中MVP架构实践小技巧

view和model通过presenter进行交互,切断直接联系。

在使用该架构后,虽然分层清晰了,但是它有个缺点, presenter中粘合接口过多

我们知道,mvp各层的交互都是通过接口来完成的,presenter作为中介者,需要实现 view操作model层的接口model层操作UI的接口 。而presenter实现这些接口时,大部分是 简单的调用model和view的接口,并没有其他额外操作 ,这样会导致presenter中粘合方法过多,并且新增接口,presenter也需要新增实现。所以,当功能复杂时,接口暴增,presenter中也会有越来越多的接口实现,同时也不利于维护。

先看个简单的弹幕例子,介绍下上面所说的问题。

Interface

// presenter提供的给view调用的接口
@protocol DanmuPresenterInterface <NSObject>
@optional
/// 清除聊天记录
- (void)cleanChats;
@end
复制代码
// view提供的给presenter调用的接口
@protocol DanmuViewInterface <NSObject>

@optional
// reload
- (void)reloadTableView;
@end
复制代码
// model层调用presenter,更新ui接口
@protocol DanmuDataOutputInterface <NSObject>

@optional
// reload
- (void)reloadTableView;
@end
复制代码
// prenseter调用model层,更新数据接口
@protocol DanmuDataInterface <NSObject>
@optional
/// 清除聊天记录
- (void)cleanChats;
@end
复制代码

Presenter

@interface DanmuPresenter()
// 数据层接口
@property (nonatomic, strong) id<DanmuDataInterface> dataManager;
// ui层接口
@property (nonatomic, weak) id<DanmuViewInterface> danmuViewInterface;
@end

@implementation DanmuPresenter

// presenter提供的给view调用的接口
#pragma mark - DanmuPresenterInterface
/// 清除聊天记录
- (void)cleanChats {
	[self.dataManager cleanChats];
}

// 实现model层调用更新ui接口
#pragma mark - DanmuDataOutputInterface
// reload
- (void)reloadTableView {
	[self.danmuViewInterface reloadTableView];
}

@end
复制代码

这个例子中,交互关系如下:

iOS中MVP架构实践小技巧

在view中的调用如下:

// self.presenterInterface为presenter
[self.presenterInterface cleanChats];
复制代码

在dataManager中调用如下:

// self.DanmuDataOutputInterface为presenter
[self.DanmuDataOutputInterface reloadTableView];
复制代码

从上面可以看出,如果 DanmuPresenterInterface、DanmuDataOutputInterface 有新增接口, presenter 中必须新增相应实现,比较麻烦。

实际上,在 danmuView 中调用 cleanChats 时, presenter 只是起了一层中转的作用,内部还是直接调用的 dataManager 的接口。对于这种类型的接口来说,会极大的增加 presenter 的接口实现方法数。

所以,在重构过程中,为了减少粘合接口,考虑直接将 消息转发到对应的实例 中,不需要写实现方法。如下所示。

  • 如果是 danmuView 通过 DanmuPresenterInterface 接口( 最后实际上是调用DanmuDataInterface操作model数据 ),则直接转发到 dataManager
  • 如果是 dataManager 调用 DanmuDataOutputInterface 接口来更新UI,则直接转发到 danmuView
// 由于presenter作为中介者,需要实现view操作model层的接口(具体实现为dataManger),model层操作UI的接口(具体实现为chatView),这样会导致粘合方法过多,并且新增接口,presenter也需要新增实现。故使用消息转发来简化处理。
- (id)forwardingTargetForSelector:(SEL)aSelector {
    // 转发DanmuDataInterface实现到dataManager
    struct objc_method_description omd = protocol_getMethodDescription(@protocol(DanmuDataInterface), aSelector, NO, YES);
    if (omd.name != NULL) {
        if ([self.dataManager respondsToSelector:aSelector]) {
            return self.dataManager;
        }
    }
    
    // 转发DanmuDataOutputInterface实现到danmuView
    omd = protocol_getMethodDescription(@protocol(DanmuDataOutputInterface), aSelector, NO, YES);
    if (omd.name != NULL) {
        if ([self.danmuViewInterface respondsToSelector:aSelector]) {
            return self.danmuViewInterface;
        }
    }
    
    return [super forwardingTargetForSelector:aSelector];
}
复制代码

这样, DanmuDataInterface、DanmuDataOutputInterface 中的接口在 presenter 中的实现均可去除。在 dataManager 调用的地方为 [self.uiInterface reloadTableView] ,注意这里不能判断 respondsToSelector ,因为 presenter 并没有实现这些方法,所以判断了不会走。

但是,这种做法是有限制的。要求presenter中实现的接口,是没有做任何额外的逻辑,而是直接调用model层或者ui层的实现。

比如,下面的实现另外调用了 [self xx] ,就不适用了。

#pragma mark - DanmuPresenterInterface
/// 清除聊天记录
- (void)cleanChats {
	// do something
	[self xx];
	[self.dataManager cleanChats];
}
复制代码

以上,就是mvp实践过程的小结。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

创新者的窘境(全新修订版)

创新者的窘境(全新修订版)

克莱顿•克里斯坦森 / 胡建桥 / 中信出版社 / 2014-1-1 / 48.00元

全球商业领域中,许多企业曾叱咤风云,但面对市场变化及新技术的挑战,最终惨遭淘汰。究其原因,竟然是因为它们精于管理,信奉客户至上等传统商业观念。这就是所有企业如今都正面临的“创新者的窘境”。 在《创新者的窘境》中,管理大师克里斯坦森指出,一些看似很完美的商业动作——对主流客户所需、赢利能力最强的产品进行精准投资和技术研发——最终却很可能毁掉一家优秀的企业。他分析了计算机、汽车、钢铁等多个行业的......一起来看看 《创新者的窘境(全新修订版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换