架构设计之MVP模式

这几天思考项目重构的问题,我就啰嗦两句。项目重构说白了就是为controller减负,解耦合。之前项目都是使用mvc模式写的,发现这样写有个弊端,就是一堆代码逻辑都堆积在controller里面,导致有些类文件庞大,有的多达上千行的代码量,阅读起来十分困难,更别说重用了,改个bug都困难。

大家有兴趣的话可以阅读下唐巧的被误解的 MVC 和被神化的 MVVM

站在大牛的肩膀上学习,总是事半功倍的。下面我们来说下MVP架构,插一句,没有任何架构设计是完美的,我们只能给不同的需求制定不同的架构设计,去降低耦合,提高复用。这是MVPDemo,需要的话自行下载。

这是MVP架构设计图,第一次画,有些粗糙
MVP架构图

下面是具体的代码实现:
先来看下类结构


高清无码图

首先来定义一个view的协议,用来处理数据回调,上代码:
#import <Foundation/Foundation.h>

@protocol BaseViewProtocol <NSObject>

- (void)showRemindTitle:(NSString *)message;

@optional
- (void)testTouchAction:(NSInteger)index;
@end

接下来在TabViewController里面去写需求,让P 层执行

@interface TableViewController ()<BaseViewProtocol>

//V 层包括UIView 和UIViewController及子类,需要持有P 层的实例对象
@property (nonatomic, strong) HomePresenter *presenter;

@end

@implementation TableViewController

- (void)viewDidLoad {
[super viewDidLoad];

//初始化一个P对象
_presenter = [[HomePresenter alloc] init];

//使用协议绑定进行数据传输
_presenter.protocol = self;

//显示head view,这里在P层创建了headView,当然也可以在Controller里面创建,传入P层
self.tableView.tableHeaderView = _presenter.headView;

[_presenter loadData];

}

- (void)showRemindTitle:(NSString *)message{
    if (message) {
      //show view
      [[[UIAlertView alloc] initWithTitle:@"温馨提示" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil] show];
    }
}

MVP中主要代码集中在P层,下面是P层代码逻辑:

@interface HomePresenter ()<BLoopImageViewDelegate>

@end

/**
 *  P 层作为协调者(中介),需要持有M 层和V 层的对象的引用
 *  适当的时候去协调他们的更新逻辑
 */
@implementation HomePresenter


- (BLoopImageView *)headView{
if (!_headView) {
    _headView = [[BLoopImageView alloc] initWithFrame:CGRectMake(0, 0, Screen_bounds.size.width, 240) delegate:self imageItems:nil isAuto:YES];
}
    return _headView;
}

- (void)setProtocol:(id<BaseViewProtocol>)protocol{
    _protocol = protocol;
}

- (void)loadData{
    [HomeListModel startGETURL:^(NSArray *info, NSString *error) {
     if (error) {
          //当请求出错时需要回调给出提示信息
          if (self.protocol) {
             [self.protocol showRemindTitle:error];
          }
     } else {
            [self.headView setItemsArr:info];
        }
    }];
}

#pragma mark
- (void)foucusImageFrame:(BLoopImageView *)imageView didSelectItem:(BLoopImageItem *)item{
    NSLog(@"item.title = %@",item.title);
    [self.protocol testTouchAction:item.tag];

}
- (void)foucusImageFrame:(BLoopImageView *)imageView currentItem:(NSInteger)index{
    NSLog(@"index = %zd",index);
}

- (void)cancelHeadView{
    self.headView = nil;
}

M层代码就变得很清爽了,只专一的去做数据处理,并组织好UI 显示的数据,看代码:

@implementation HomeListModel

+ (void)startGETURL:(void (^)(NSArray *info, NSString *error))block{
    [[BKNetworking share] get:@"http://bapi.baby-kingdom.com/index.php?mod=stand&op=index&ver=3.6.0&app=ios" completion:^(BKNetworkModel *model, NSString *netErr) {
        if (netErr) {
            block(nil, netErr);
        } else {
            if (model.status) {
                NSDictionary *data = model.data;
                if ([data isKindOfClass:[NSDictionary class]]) {
                    NSArray *items = [self loadPackageData:data[@"lists"]];
                
                    //创建model
                    block ( items, nil );
                }
            }
        }
    }];
}


//组装数据并返回
+ (NSArray *)loadPackageData:(NSArray *)images{
    //添加最后一张图 用于循环
    int length = (unsigned)images.count;
    NSMutableArray *itemArray = [NSMutableArray arrayWithCapacity:length+2];
    if (length > 1)
    {
        NSDictionary *dict = images[length-1];
        BLoopImageItem *item = [[BLoopImageItem alloc] initWithDict:dict tag:-1];
        [itemArray addObject:item];
    }
    for (int i = 0; i < length; i++)
    {
        NSDictionary *dict = images[i];
        BLoopImageItem *item = [[BLoopImageItem alloc] initWithDict:dict tag:i];
        [itemArray addObject:item];
    }
    //添加第一张图 用于循环
    if (length >1)
    {
        NSDictionary *dict = images[0];
        BLoopImageItem *item = [[BLoopImageItem alloc] initWithDict:dict tag:length];
        [itemArray addObject:item];
    }

    return itemArray;

}

@end

参考文章:

iOS 软件架构 - MVC, MVP, MVVM 和 VIPER 「译」

第一次设计到架构,可能还有问题,希望大家一起交流讨论,谢谢!


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容