MVC模式
- MVC模式–全称Model View Controller,模型(model)视图(view)控制器(controller),它有三个层,分别负责其不同的职责
View层–用于存放视图,在这个层,我们可以对页面及控件进行布局
Model层–模型,模型一般都有很好的可复用性,通过Model层,我们可以统一管理一些数据
Controller层–控制器,充当一个CPU的功能,即该应用程序所有的工作都由Controller统一调控,其负责处理View和Model的事件。
MVC模式降低了各个环节耦合性,优化Controller的代码量。
MVC模式中各个层的关系图:
可见,在MVC模式中,Model层和View层之间不直接通信,它们是靠着Controller通信的。
- Controller和View之间可以通信,Controllor通过outlet(输出口)控制View,View可以通过target-action、delegate或者dataSource(想想UITableVeiwDatasource)来和Controller通信;
- Controller在接收到View传过来的交互事件(View就是完成让人和程序的交互的呀,比如按B1按钮)之后,经过一些判断和处理,把需要Model处理的事件递交给Model处理(比如刚才的例子中的保存到数据库),Controller对Model使用的是API;
- Model在处理完数据之后,如果有需要,会通过Notification或者KVO的方式告知Controller,事件已经处理完,Controller再经过判断和处理之后,考虑下一步要怎么办(是默默无闻的在后台操作,还是需要更新View,这得看Controller的“脸色”行事)。这里的无线天线很有意思,Model只负责发送通知,具体谁接收这个通知并处理它,Model并不关心,这一点非常重要,是理解Notification模式的关键。
MVC案例:登录注册
- 首先,在我们的项目管理器中将我们的层分好:分别是M(Model层),V(View层),C(Controller层)
- 在我的Model层中,我创建了一个可变字典,该字典用于存储账户信息,字典的key是账号,value是密码。在Model层中有两个方法,一个方法用于登录时调用该方法来向Controller层发送在Model存储的账户数据,另一个方法用于注册时将从Controller传来的账号密码存入字典,在Model层还需要重写MModel的init方法。
- 在我的View层中,我创建了两个View,分别用于登录和注册账号,并给其布局了相应的页面控件
- 在我的Controller层中,我创建了两个Controller,用于控制我创建的对应的两个View,在控制登录页面的Controller中,我创建了MModel和VView的实例对象,然后为VView中的控件添加相应的事件函数,包括对用户输入的账号密码进行判断等。并且使用通知传值来接收和发送信息给MModel。同时给VView中的一个按钮添加了跳转到注册页面的函数。
- 在负责注册功能的Controller中,我将该Controller中的MModel的实例对象直接赋为前一个Controller的MModel实例对象,确保MModel一直是同一个实例对象。然后给VzhuCeView的注册按钮添加事件函数,在该函数中通过调用MModel的注册方法将用户输入的账号密码传给MModel层的可变字典中。并且通过通知传值传回反馈。
代码实现:
- M层:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MModel : NSObject
@property (nonatomic, strong) NSMutableDictionary* zhangHuDictionary;
- (void)dengLu;
- (void)zhuCe: (NSString*)zhangHao :(NSString*)miMa;
@end
NS_ASSUME_NONNULL_END
#import "MModel.h"
@implementation MModel
//重写初始化方法
- (MModel*) init {
if (self = [super init]) {
self.zhangHuDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)dengLu {
//通知方法,发送通知并携带字典将字典传给Controller
[[NSNotificationCenter defaultCenter] postNotificationName:@"dengLu" object:self userInfo:self.zhangHuDictionary];
NSLog(@"登录时:%@", self.zhangHuDictionary);
}
- (void)zhuCe: (NSString*)zhangHao :(NSString*)miMa {
[self.zhangHuDictionary setObject:miMa forKey:zhangHao];
//通知方法,发送通知给Controller完成注册反馈
[[NSNotificationCenter defaultCenter] postNotificationName:@"zhuCe" object:self userInfo:self.zhangHuDictionary];
NSLog(@"注册后:%@", self.zhangHuDictionary);
}
@end
- V层:VView:
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface VView : UIView
@property (nonatomic, strong) UITextField *zhangHaoTextField;
@property (nonatomic, strong) UITextField *miMaTextField;
@property (nonatomic, strong) UIButton *dengLuButton;
@property (nonatomic, strong) UIButton *zhuCeButton;
- (void)viewInit;
@end
NS_ASSUME_NONNULL_END
#import "VView.h"
@implementation VView
- (void)viewInit {
self.backgroundColor = [UIColor whiteColor];
self.zhangHaoTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
self.zhangHaoTextField.borderStyle = UITextBorderStyleRoundedRect;
self.zhangHaoTextField.placeholder = @"账号";
[self addSubview:self.zhangHaoTextField];
self.miMaTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 350, 200, 50)];
self.miMaTextField.placeholder = @"密码";
self.miMaTextField.borderStyle = UITextBorderStyleRoundedRect;
[self addSubview:self.miMaTextField];
self.dengLuButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.dengLuButton setTitle:@"登录" forState:UIControlStateNormal];
self.dengLuButton.frame = CGRectMake(100, 500, 90, 80);
[self addSubview:self.dengLuButton];
self.zhuCeButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.zhuCeButton setTitle:@"注册" forState:UIControlStateNormal];
self.zhuCeButton.frame = CGRectMake(200, 500, 90, 80);
[self addSubview:self.zhuCeButton];
}
@end
VzhuCeView:
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface VzhuCeView : UIView
@property (nonatomic, strong) UITextField *zhangHaoTextField;
@property (nonatomic, strong) UITextField *miMaTextField;
@property (nonatomic, strong) UIButton *zhuCeButton;
- (void)viewInit;
@end
NS_ASSUME_NONNULL_END
#import "VzhuCeView.h"
@implementation VzhuCeView
- (void)viewInit {
self.backgroundColor = [UIColor whiteColor];
self.zhangHaoTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
self.zhangHaoTextField.borderStyle = UITextBorderStyleRoundedRect;
self.zhangHaoTextField.placeholder = @"账号";
[self addSubview:self.zhangHaoTextField];
self.miMaTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 350, 200, 50)];
self.miMaTextField.placeholder = @"密码";
self.miMaTextField.borderStyle = UITextBorderStyleRoundedRect;
[self addSubview:self.miMaTextField];
self.zhuCeButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.zhuCeButton setTitle:@"注册" forState:UIControlStateNormal];
self.zhuCeButton.frame = CGRectMake(200, 500, 90, 80);
[self addSubview:self.zhuCeButton];
}
@end
- C层:ViewController:
#import <UIKit/UIKit.h>
#import "MModel.h"
#import "VView.h"
#import "TiaoZhuanViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface ViewController : UIViewController
//声明Model和View层的属性
@property (nonatomic, strong) MModel *mModel;
@property (nonatomic, strong) VView *vView;
@end
NS_ASSUME_NONNULL_END
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建Model和View层的实例对象
self.vView = [[VView alloc] initWithFrame:self.view.bounds];
[self.vView viewInit];
//给View中的控件添加事件函数
[self.vView.zhuCeButton addTarget:self action:@selector(pressZhuCeTiaoZhuan) forControlEvents:UIControlEventTouchUpInside];
[self.vView.dengLuButton addTarget:self action:@selector(pressDengLu) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.vView];
self.mModel = [[MModel alloc] init];
//注册通知,接收从Model层传来的字典,当接收到通知时,执行事件函数
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dengLu:) name:@"dengLu" object:nil];
}
//视图切换
- (void)pressZhuCeTiaoZhuan {
TiaoZhuanViewController *tiaoZhuan = [[TiaoZhuanViewController alloc] init];
[self presentViewController:tiaoZhuan animated:YES completion:nil];
tiaoZhuan.mModel = self.mModel;
}
//登录按钮的事件函数是执行Model对象中的登录方法
- (void)pressDengLu {
[self.mModel dengLu];
}
//接收到通知后执行,登录时对账号密码进行判断
- (void)dengLu: (NSNotification*)notification {
NSString *zhangHaoStr = [NSString stringWithFormat:@"%@",self.vView.zhangHaoTextField.text];
if ([self.vView.miMaTextField.text isEqual: notification.userInfo[zhangHaoStr]]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"登录成功" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:nil];
[self presentViewController:alert animated:YES completion:nil];
[alert addAction:action];
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"登录失败" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:nil];
[self presentViewController:alert animated:YES completion:nil];
[alert addAction:action];
}
}
@end
TiaoZhuanViewController:
#import <UIKit/UIKit.h>
#import "VzhuCeView.h"
#import "MModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface TiaoZhuanViewController : UIViewController
@property (nonatomic, strong) VzhuCeView *zhuCeView;
@property (nonatomic, strong) MModel *mModel;
@end
NS_ASSUME_NONNULL_END
#import "TiaoZhuanViewController.h"
@interface TiaoZhuanViewController ()
@end
@implementation TiaoZhuanViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.zhuCeView = [[VzhuCeView alloc] initWithFrame:self.view.bounds];
[self.zhuCeView viewInit];
[self.zhuCeView.zhuCeButton addTarget:self action:@selector(pressZhuCe) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.zhuCeView];
//注册通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pressZhuCe:) name:@"zhuCe" object:nil];
}
//点击按钮触发事件函数,调用Model对象的注册的方法,将用户输入的账号密码存入字典
- (void)pressZhuCe {
[self.mModel zhuCe:self.zhuCeView.zhangHaoTextField.text :self.zhuCeView.miMaTextField.text];
}
- (void)pressZhuCe: (NSNotification*)notification {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"注册成功" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:nil];
[self presentViewController:alert animated:YES completion:nil];
[alert addAction:action];
}
@end