您的位置:首页 > 移动开发 > IOS开发

IOS (oc) 浅谈MVP在ios项目中的使用以及Demo

2017-02-14 19:10 435 查看
个人对于MVP思路的理解,就是开发过程中,数据和界面之间的交互,使用Presenter层管理,较于MVC模式:获取数据,构建对象,在控制器里赋值更新界面;MVP模式思路在获取数据,构造对象后,不直接在控制器中做界面交互逻辑,而是使用控制器层管理,将业务逻辑独立出来,这样便于代码的后期维护,同时降低了控制器的负担以及数据模型和控制器、界面之间的耦合性。

本篇文章以登录界面为例,使用ios的OC语言展示我对于MVP的理解:

登录界面:



首先创建一个空的项目,名为MVPDemoOC,

建立一个名为Classes的文件夹,代码将在该文件夹中:



文件夹UI放置控制器,Biz放置业务逻辑,Model放置数据模型,Presenter放置控制器相应的管理者,View放置管理者和控制器的交互层(注意:文件夹View区别于UIView,文章中实例并未用到UIView文件夹,但在实际开发中,例如TableViewController的cell应放置在UIView中)

在Main.stroyboard中搭建界面,并在ViewController中连接,代码:

#import "ViewController.h"

@interface ViewController ()

{

    __weak IBOutlet UITextField *userName;

    

    __weak IBOutlet UITextField *passWord;

    __weak IBOutlet UIActivityIndicatorView *activityBar;

}

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    activityBar.hidden = true ;

    // Do any additional setup after loading the view, typically from a nib.

}

- (IBAction)loginClick:(UIButton *)sender {

   

}

- (IBAction)clearClick:(UIButton *)sender {

}

@end

建立登录的数据模型(UserM
4000
odel):

在UserModel.h中,代码:

#import <Foundation/Foundation.h>

@interface UserModel : NSObject

@property ( nonatomic , copy ) NSString * username;

@property ( nonatomic , copy ) NSString * password;

@end

在UserModel.m中,代码:

#import "UserModel.h"

@implementation UserModel

@end

建立管理者ViewPresenter的类,包含.h和.m文件,继承NSObject

建立管理者和控制器之间的交互View层,名为MainView。分析:由于View层是用于控制器和管理者(ViewPresenter)的交互,对于管理者,对MainView调用的是一个MainView对象;而在控制器中,需要实现MainView的方法,即为协议。所以MainView可以用协议来实现,在代码中,只需创建MainView.h文件即可(文章后面创建协议均为.h文件,不做单独描述)。代码:

@protocol MainView <NSObject>

@end

现在项目目录如图:



至此,进行分析如下:

界面需要输入账号,密码,然后点击登录时,加载动画展示,做登录请求,判断账号密码是否正确,返回成功或是失败,加载动画隐藏。

点击清空按钮,清空账号,清空密码。

管理者需要有登录和清空的事件,还需使用MainView对象,进行和控制器的交互,在控制器中创建管理者时,还需设置交互的View层链接,即为persenter.maivView = self ,该代码可以在管理者对象创建的构造函数中直接实现。则在代码ViewPresenter.h中:

#import <Foundation/Foundation.h>

#import "MainView.h"

@interface ViewPresenter : NSObject

#pragma mark - 介于控制器和管理者的交互对象

@property ( nonatomic , assign ) id<MainView> mainView;

#pragma mark - 控制器的登录事件

- (void) login ;

#pragma mark - 控制器的清空事件

- (void) clear ;

#pragma mark - 管理者的构造函数

- (instancetype)initWithMainView : (id<MainView>) mainView ;

@end

在ViewPresenter.m的实现中,登录需要使用_mainView对象加载蒙版动画,获得账号,获得密码,登录成功或是失败,需要_mainView隐藏加载动画;在管理者清空动作中,需要_mainView对象清空账号,清空密码。以上分析后,可以确定在MainView.h中(即View协议层中),需要实现代码:

@protocol MainView <NSObject>

#pragma mark - 展示加载动画

- (void) showProgress ;

#pragma mark - 隐藏加载动画

- (void) dismiss ;

#pragma mark - 获得账号

- (NSString *) getUserName ;

#pragma mark - 获得密码

- (NSString *) getPassWord ;

#pragma mark - 清空账号

- (void) clearUserName ;

#pragma mark - 清空密码

- (void) clearPassWord ;

@end

管理者ViewPresente.m中代码如下:

#import "ViewPresenter.h"

@implementation ViewPresenter

#pragma mark - 管理者的构造函数

- (instancetype)initWithMainView : (id<MainView>) mainView {

    if (self = [super init]) {

        _mainView = mainView ;//设置管理者的MainView

    }

    return self ;

}

#pragma mark - 控制器的登录事件

- (void) login {

    [_mainView showProgress];

    //登录

    

}

#pragma mark - 控制器的清空事件

- (void) clear {

    [_mainView clearUserName];

    [_mainView clearPassWord];

}

@end

登录时的业务逻辑层分析:需要登录的对象,调用一个登录函数,传参为账户。密码。监测登录成功或是失败。

则在业务层创建一个登录用到的类,名称UserLogin,同时创建登录结果的监听协议LoginListener。

在UserLogin.h中,代码:

#import <Foundation/Foundation.h>

#import "LoginListener.h"

@interface UserLogin : NSObject

/**

 *  登录

 *

 *  @param userName      账号

 *  @param passWord      密码

 *  @param loginListener 登录的监听

 */

- (void) loginWithUserName:(NSString *) userName

              WithPassWord:(NSString *) passWord

         WithLoginListener: (id<LoginListener>) loginListener ;

@end
在LoginListener.h中,登录监听的结果有两种:成功,失败,监听结果可以传参,成功时返回登录的UserModel对象,失败返回失败的信息字符串。代码如下:

@class UserModel ;

@protocol LoginListener <NSObject>

- (void) Failure:(NSString *) errormessage ;

- (void) Sucess: (UserModel *) model ;

@end

在UserLogin.m中,代码如下:

#import "UserLogin.h"

#import "UserModel.h"

@implementation UserLogin

/**

 *  登录

 *

 *  @param userName      账号

 *  @param passWord      密码

 *  @param loginListener 登录的监听

 */

- (void) loginWithUserName:(NSString *) userName

              WithPassWord:(NSString *) passWord

         WithLoginListener: (id<LoginListener>) loginListener {

    //此处模拟异步线程

    dispatch_queue_t dqt = dispatch_queue_create("login", nil);

    dispatch_async(dqt, ^{

        //异步线程中

        sleep(2);//线程阻塞2秒,用于展示加载动画

        

        //此处返回主线程

        dispatch_queue_t maindqt = dispatch_get_main_queue() ;

        dispatch_async(maindqt, ^{

           //主线程中

            

            //判断登录的结果

            if ([userName isEqualToString:@"fei"]&&[passWord isEqualToString:@"123"]) {

                //登录成功

                UserModel * m = [[UserModel alloc]init];

                m.username = userName;

                m.password = passWord ;

                [loginListener Sucess:m];

            } else {

                //登录失败

                [loginListener Failure:@"你的账号或是密码不正确"];

            }

        });

    });

}

@end

业务逻辑层处理完成,在管理者ViewPresenter中,实现登录调用需声明登录UserLogin的变量,并在构造函数中实例化该变量,并且ViewPresenter需要遵循登录监听的协议LoginListener,代码如下

#import "ViewPresenter.h"

#import "UserLogin.h"

#import "UserModel.h"

@interface ViewPresenter ()<LoginListener,UIAlertViewDelegate>//遵循登录监听协议LoginListener

{

    //声明登录对象变量

    UserLogin * _userLogin ;

}

@end

@implementation ViewPresenter

#pragma mark - 管理者的构造函数

- (instancetype)initWithMainView : (id<MainView>) mainView {

    if (self = [super init]) {

        _mainView = mainView ;//设置管理者的MainView
        _userLogin = [[UserLogin alloc]init];

    }

    return self ;

}

#pragma mark - 控制器的登录事件

- (void) login {

    [_mainView showProgress];
    //登录

    [_userLogin loginWithUserName:[_mainView getUserName] WithPassWord:[_mainView getPassWord] WithLoginListener:self];

}
#pragma mark - 登录监听 失败

- (void)Failure:(NSString *)errormessage {

    [_mainView dismiss];

    UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"登录失败" message:errormessage delegate:self cancelButtonTitle:@"知道了" otherButtonTitles: nil];

    [alert show];

    

}

#pragma mark - 登录监听 成功

- (void)Sucess:(UserModel *)model {

    [_mainView dismiss];

    NSString *message = [NSString stringWithFormat:@"你的账号:%@ 登录成功",model.username];

    UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"登录成功" message:message delegate:self cancelButtonTitle:@"知道了" otherButtonTitles: nil];

    [alert show];

}

#pragma mark - 控制器的清空事件

- (void) clear {

    [_mainView clearUserName];

    [_mainView clearPassWord];

}

@end

以上业务逻辑层处理完毕,回到控制器中,声明管理者变量,实例化该变量,调用登录和清空事件遵循MainView协议,代码如下:

#import "ViewController.h"

#import "ViewPresenter.h"

#import "MainView.h"

@interface ViewController ()<MainView>//遵循View层的交互协议

{

    

    __weak IBOutlet UITextField *userName;

    

    __weak IBOutlet UITextField *passWord;

    __weak IBOutlet UIActivityIndicatorView *activityBar;

    

    //声明管理者变量

    ViewPresenter *_presenter ;

}

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    

    activityBar.hidden = true ;

    

    //实例化管理者变量

    _presenter = [[ViewPresenter alloc]initWithMainView:self];

    // Do any additional setup after loading the view, typically from a nib.

}

- (IBAction)loginClick:(UIButton *)sender {

    [_presenter login];//登录事件

}

- (IBAction)clearClick:(UIButton *)sender {

    [_presenter clear];//清空事件

}

//=========== MainView 的协议实现 ===================

#pragma mark - 展示加载动画

- (void) showProgress {

    activityBar.hidden = false ;

}

#pragma mark - 隐藏加载动画

- (void) dismiss {

    activityBar.hidden = true ;

}

#pragma mark - 获得账号

- (NSString *) getUserName {

    return userName.text ;

}

#pragma mark - 获得密码

- (NSString *) getPassWord {

    return passWord.text ;

}

#pragma mark - 清空账号

- (void) clearUserName {

    userName.text = @"" ;

}

#pragma mark - 清空密码

- (void) clearPassWord {

    passWord.text = @"" ;

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end
Demo的下载地址:
http://download.csdn.net/detail/flytosky_l/9755195
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐