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的方法有两种:
- 使用interface Builder的方式,这种方式就是使用nib文件,是通常说的“拖控件”的方式。
实际编程中,我梦如果用Interface Builder方式创建了UIView对象,那么,initWithFrame方法是不会被调用的,因为nib文件已经知道如何初始化该View,这时候会调用initWithCoder方法,我们可以用initWithCoder方法来重新定义我们在nib中已经设置好的各项属性。 - 使用编程方式,也就是我们声明一个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的全部代码了。