[iOS]- MVC模式基础

MVC介绍

MVC(Model–View–Controller)模式是软件工程中的一种软件架构模式,它把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

MVC 模式的目的是实现一种动态的程序设计,简化后续对程序的修改和扩展,并且使程序某一部分的重复利用成为可能。除此之外,MVC 模式通过对复杂度的简化,使程序的结构更加直观。软件系统在分离了自身的基本部分的同时,也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长进行相关的分组:

▪ 模型(Model):程序员编写程序应有的功能(实现算法等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。

▪ 控制器(Controller):负责转发请求,对请求进行处理。

▪ 视图(View):界面设计人员进行图形界面设计

MVC模式的描述如下图所示:


▪ Controller和View之间可以通信,Controllor通过outlet(输出口)控制View,View可以通过target-action、delegate或者data source(想想UITableVeiwDatasource)来和Controller通信;

▪ Controller在接收到View传过来的交互事件,比如按钮的事件函数之后,经过一些判断和处理,把需要Model处理的事件递交给Model处理,Controller对Model使用的是API;

▪ Model在处理完数据之后,如果有需要,会通过Notification或者KVO的方式告知Controller,事件已经处理完,Controller再经过判断和处理之后,在进行进一步处理。这里的无线天线很有意思,Model只负责发送通知,具体谁接收这个通知并处理它,Model并不关心,这一点非常重要,是理解Notification模式的关键。

▪ Model和View之间不直接通信

简单来说//MVC就是M中负责在数据库中存取数据并进行数据处理,V中负责编写需要显示的模型但不写按钮事件函数等,C中负责写模型的事件函数等具体内容并和其他的Controller产生联系(比如继承协议等)

登陆注册demo

▪首先新建M V C三个文件夹(每个View创建一套,需要几个View就创建几个文件夹)
(以下以登陆界面的View所需的文件夹为例,注册界面同下)
▪新建一个名为loadMode的类,继承自NSObject
▪新建一个名为loadView的类,继承自UIView
▪将其拖到相应的文件夹下
▪新建一对用于登陆成功后所需要跳到界面的newViewController文件

结果如下:
请添加图片描述
根据MVC思想,在loadView文件中,我们应该写声明UITextField和UIButton并设置其显示位置颜色等具体内容

loadView.h中:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface loadView : UIView

@property (nonatomic, strong) UIButton *loadButton;
@property (nonatomic, strong) UIButton *registerButton;
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *passTextField;

- (void) InitView;//view初始化

@end

NS_ASSUME_NONNULL_END

loadView.m中:

#import "loadView.h"

@implementation loadView

- (void) InitView {
    
    _loadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_loadButton setFrame:CGRectMake(80, 400, 100, 50)];
    [_loadButton setTitle:@"load" forState:UIControlStateNormal];
    [_loadButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self addSubview:_loadButton];
    
    _registerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_registerButton setFrame:CGRectMake(230, 400, 100, 50)];
    [_registerButton setTitle:@"register" forState:UIControlStateNormal];
    [_registerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self addSubview:_registerButton];
    
    
    _nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 200, 300, 50)];
    _nameTextField.layer.masksToBounds = YES;
    _nameTextField.layer.cornerRadius = 8.0;
    _nameTextField.layer.borderWidth = 2;
    _nameTextField.layer.borderColor = [UIColor blackColor].CGColor;
    _nameTextField.placeholder = @"nameWord";
    [self addSubview:_nameTextField];
    
    _passTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 280, 300, 50)];
    _passTextField.layer.masksToBounds = YES;
    _passTextField.layer.cornerRadius = 8.0;
    _passTextField.layer.borderWidth = 2;
    _passTextField.layer.borderColor = [UIColor blackColor].CGColor;
    _passTextField.secureTextEntry = YES;
    _passTextField.placeholder = @"passWord";
    [self addSubview:_passTextField]; 
}

@end

loadView.m中,我们重写init函数来初始化View,原因是我们的编程方式申明,创建UIView对象时,使用initWithFrame方法。
其中,初始化UIView的方法有两种:

  1. 使用interface Builder的方式,这种方式就是使用nib文件,是通常说的“拖控件”的方式。
    实际编程中,我梦如果用Interface Builder方式创建了UIView对象,那么,initWithFrame方法是不会被调用的,因为nib文件已经知道如何初始化该View,这时候会调用initWithCoder方法,我们可以用initWithCoder方法来重新定义我们在nib中已经设置好的各项属性。
  2. 使用编程方式,也就是我们声明一个UIView的子类,然后用“手工”编写代码的方式
    实际编程中,我们使用编程方式下,来创建一个UIView或者创建UIView的子类,这时候,将调用initWithFrame方法,来实例化UIView,需要注意的是,如果在子类中重载initWithFrame方法,必须先吊用父类的initWithFrame方法,再对自定义的UIView子类进行初始化操作。

根据MVC思想,我们将loadView中的Button的target-action(事件函数),写在viewController文件中,按照MVC的思想,V里面不进行数据处理,而是要在C里面统一调控由C还是M来处理数据。本例中,我们是在C里面处理,所以我把targe-action方法写到C里面。由于本例在loadView和loadModel中定义的方法为实例方法,所以需要实例化loadView和loadModel来调用这些方法:
viewController.h中:

#import <UIKit/UIKit.h>
#import "registerViewController.h"
#import "loadView.h"
#import "loadModel.h"

NS_ASSUME_NONNULL_BEGIN

//此处继承了注册界面的Controller.h中自定义的用于协议传值的协议及
@interface ViewController : UIViewController
<RegisterDelegate> 

@property (nonatomic, strong) loadView *myView;
@property (nonatomic, strong) loadModel *myModel;

@end

NS_ASSUME_NONNULL_END

在viewController.m中:

#import "ViewController.h"
#import "newViewController.h"
#import "registerViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    _myView = [[loadView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    [_myView InitView];
    [_myView.loadButton addTarget:self action:@selector(pressLoad) forControlEvents:UIControlEventTouchUpInside];
    [_myView.registerButton addTarget:self action:@selector(pressRegister) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_myView];
    
    _myModel = [[loadModel alloc] init];
    [_myModel modelInit];
    
}

- (void) pressLoad {
    
    //以前注册的账号和密码也可以登陆,数组相当于储存已注册数据了
    for (int i = 0; i < _myModel.nameArr.count; i++) {
        if ([_myView.nameTextField.text isEqualToString:_myModel.nameArr[i]] && [_myView.passTextField.text isEqualToString:_myModel.passArr[i]]) {
            newViewController *new = [[newViewController alloc] init];
            [self presentViewController:new animated:NO completion:nil];
        }
    }
    
}

- (void) pressRegister {
    
    registerViewController *RegistViewController = [[registerViewController alloc] init];
    RegistViewController.registerDelegate = self;
    [self presentViewController:RegistViewController animated:NO completion:nil];
    
}

- (void) passName:(NSString *) name passPass:(NSString *)pass {
    [_myModel.nameArr addObject:name];
    [_myModel.passArr addObject:pass];
}

@end

可以看到我们在viewController.m文件中编写了MVC的V中的Button的target-action方法

按照MVC的思想,M主要用于数据的处理,所以在这个案例中我将存放账号和密码的数组放入M中。
loadModel.h中:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface loadModel : NSObject

@property (nonatomic, strong) NSMutableArray *nameArr;
@property (nonatomic, strong) NSMutableArray *passArr;

- (void) modelInit;

@end

NS_ASSUME_NONNULL_END

在loadModel.m文件中:

//在这个文件中,我们对存账号密码的数组进行了初始化,并设定了初始的一个账号密码
#import "loadModel.h"

@implementation loadModel

- (void) modelInit {
    
    _nameArr = [[NSMutableArray alloc] init];
    _passArr = [[NSMutableArray alloc] init];
    [_nameArr addObject:@"123"];
    [_passArr addObject:@"111"];
    
}

@end

到此为止,登陆界面就算是写完了,注册界面的MVC原理与其一致,具体代码如下:
registerView.h中:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface registerView : UIView

@property (nonatomic, strong) UIButton *loadButton;
@property (nonatomic, strong) UIButton *registerButton;
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *passTextField;

- (void) InitView;//view初始化

@end

NS_ASSUME_NONNULL_END

registerView.m中:

#import "registerView.h"

@implementation registerView

- (void) InitView {
    _loadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_loadButton setFrame:CGRectMake(80, 400, 100, 50)];
    [_loadButton setTitle:@"back" forState:UIControlStateNormal];
    [_loadButton setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
    [self addSubview:_loadButton];
    
    _registerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_registerButton setFrame:CGRectMake(230, 400, 100, 50)];
    [_registerButton setTitle:@"Ok" forState:UIControlStateNormal];
    [_registerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self addSubview:_registerButton];
    
    _nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 200, 300, 50)];
    _nameTextField.layer.masksToBounds = YES;
    _nameTextField.layer.cornerRadius = 5;
    _nameTextField.layer.borderWidth = 2;
    _nameTextField.layer.borderColor = [UIColor blackColor].CGColor;
    _nameTextField.placeholder = @"nameWord";
    [self addSubview:_nameTextField];
    
    _passTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 280, 300, 50)];
    _passTextField.layer.masksToBounds = YES;
    _passTextField.layer.cornerRadius = 5;
    _passTextField.layer.borderWidth = 2;
    _passTextField.layer.borderColor = [UIColor blackColor].CGColor;
    _passTextField.secureTextEntry = YES;
    _passTextField.placeholder = @"passWord";
    [self addSubview:_passTextField];
}

@end

registerViewController.h中:

#import <UIKit/UIKit.h>
#import "registerView.h"
#import "registerModel.h"

NS_ASSUME_NONNULL_BEGIN

@protocol RegisterDelegate <NSObject>

- (void) passName: (NSString *) name passPass: (NSString *) pass;

@end

@interface registerViewController : UIViewController

@property (nonatomic, strong) registerView *myView;
@property (nonatomic, strong) registerModel *myModel;
@property id <RegisterDelegate> registerDelegate;

@end

NS_ASSUME_NONNULL_END

registerViewController.m中:

#import "registerViewController.h"
#import "ViewController.h"

@interface registerViewController ()

@end

@implementation registerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    _myView = [[registerView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    [_myView InitView];
    
    [_myView.loadButton addTarget:self action:@selector(pressLoad) forControlEvents:UIControlEventTouchUpInside];
    [_myView.registerButton addTarget:self action:@selector(pressRegister) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_myView];
    
    _myModel = [[registerModel alloc] init];
    
}

- (void) pressLoad {
    
    [self dismissViewControllerAnimated:NO completion:nil];
    
}

- (void) pressRegister {
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"你已注册成功!" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *sure = [UIAlertAction actionWithTitle:@"sure" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        if ([self->_registerDelegate respondsToSelector:@selector(passName:passPass:)]) {
                    [self->_registerDelegate passName:self->_myView.nameTextField.text passPass:self->_myView.passTextField.text];
                }
        [self dismissViewControllerAnimated:NO completion:nil];
        
    }];
    
    [alert addAction:sure];
    [self presentViewController:alert animated:NO completion:nil];
}

@end

registerModel.h中:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN 

@interface registerModel : NSObject

@end

NS_ASSUME_NONNULL_END

registerModel.m中:

#import "registerModel.h"

@implementation registerModel

@end

到此就是这个登陆注册demo的全部代码了。


版权声明:本文为m0_52192682原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。