MVC
MVC是软件行业一个非常经典的架构,因为几乎所有的业务逻辑几乎都可以用这三个类来表示
两根红线表示Controller 控制view的渲染 也可以修改model
两根绿线表示view采集到的用户数据和用户事件会反馈给Controller view 可以读取model 进而展示自己
demo演示 MVCController 让 MVCView执行打印任务
场景:
- 初始化
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"MVC";
// MVCView 初始化 通过代理传递事件给 MVCController
self.myView = [[MVCView alloc] initWithFrame:CGRectMake(50, 64, 300, 400)];
self.myView.delegate = self;
// MVCModel 初始化 实例数据
self.paper = [[Paper alloc] init];
self.paper.content = @"lky";
[self.view addSubview:self.myView];
// MVCController 让 MVCView执行打印任务 或者是渲染
[self printPaper];
}
- (void)printPaper{
[self.myView printOnView:self.paper];
}
- view 可以读取model 进而展示自己
-(void)printOnView:(Paper *)paper
{
self.paper = paper;
self.backgroundColor = [UIColor lightGrayColor];
NSLog(@"%@---MVCView接收到打印任务",paper.content);
}
- view采集到的用户数据和用户事件会反馈给Controller
- (void)btnClick{
if ([self.delegate respondsToSelector:@selector(onPrintClick)]) {
[self.delegate onPrintClick];
}
}
MVP
从上图可以看出Controller不见了,多了一个Presenter 来处理逻辑关系, 实际上 Controller只对 Presenter 持有引用关系 另外一点是view和model互相都不知道彼此的存在,
- Presenterc同时持有view和model
@interface Presenter : NSObject
@property (nonatomic,strong) MVPView *mvpView;
@property (nonatomic,strong) MVPModel *mvpModel;
- (void)printTask;
@end
-(instancetype)init
{
if (self = [super init]) {
self.mvpModel = [[MVPModel alloc] init];
self.mvpModel.content = @"line 0";
self.mvpView = [[MVPView alloc] init];
self.mvpView.frame = CGRectMake(0, 100, 300, 400);
self.mvpView.delegate = self;
}
return self;
}
- Controller告诉Presenterc执行打印任务
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"MVP";
// 创建3个展示器 模型 视图
self.presenter = [[Presenter alloc] init];
[self.view addSubview:self.presenter.mvpView];
// 告诉presenter执行打印任务
[self.presenter printTask];
}
- Presenter执行打印任务 传递的不是model模型 而是model的属性
@implementation Presenter
-(void)printTask
{
[self.mvpView printOnViewWithContent:self.mvpModel.content];
}
- view响应事件 通知Presenter进行处理 这里view的代理是Presenter
@implementation MVPView
- (void)btnClick{
if (self.delegate) {
[self.delegate printDoneClick];
}
}
- Presenter处理响应事件
@implementation Presenter
#pragma MVPViewDelegate
-(void)printDoneClick{
int rand = arc4random()%10;
self.mvpModel.content = [NSString stringWithFormat:@"line %d",rand];
[self.mvpView printOnViewWithContent:self.mvpModel.content];
}
MVVM
与 MVC相比可以看出Controller不见了,多出了viewModel类来处理业务逻辑,view与viewModel之间是一个双向绑定的关系,也就是说view会监听viewModel 然后根据viewModel的变化而更新view的UI变化,在view上面如果有事件产生也会反射给viewModel来与Model进行协调处理
- 初始化
@implementation MVVMController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"MVVM";
self.vmView = [[MVVMView alloc] init];
self.vmView.frame = CGRectMake(20, 100, 300, 400);
[self.view addSubview:self.vmView];
self.vmModel = [[MVVModel alloc] init];
self.vmModel.content = @"line 0";
self.vmViewModel = [[MVVMViewModel alloc] init];
[self.vmViewModel setWithModel:self.vmModel];
[self.vmView setWithViewModel:self.vmViewModel];
}
- view与viewModel之间建立双向绑定 这里使用FBKVOController,这是一个对KVO进行封装的库
#import "MVVMView.h"
#import "NSObject+FBKVOController.h"
@interface MVVMView ()
@property (nonatomic,strong) UILabel *labelContent;
@property (nonatomic,strong) UIButton *btn;
@property (nonatomic,weak) MVVMViewModel *vmViewModel;
@end
@implementation MVVMView
-(instancetype)init{
if (self = [super init]) {
self.backgroundColor = [UIColor grayColor];
self.labelContent = [[UILabel alloc] init];
self.labelContent.backgroundColor = [UIColor whiteColor];
self.labelContent.frame = CGRectMake(50, 100, 200, 40);
[self addSubview:self.labelContent];
self.btn = [UIButton buttonWithType:UIButtonTypeCustom];
self.btn.frame = CGRectMake(80, 300, 80, 40);
self.btn.backgroundColor = [UIColor lightGrayColor];
[self.btn setTitle:@"点击" forState:UIControlStateNormal];
[self addSubview:self.btn];
[self.btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)btnClick{
[self.vmViewModel onPrintClick];
}
-(void)setWithViewModel:(MVVMViewModel *)viewModel
{
__weak typeof(self) weakSelf = self;
self.vmViewModel = viewModel;
[self.KVOController observe:viewModel keyPath:@"contentStr" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial block:^(id _Nullable observer, id _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
NSString *newContent = change[NSKeyValueChangeNewKey];
weakSelf.labelContent.text = newContent;
}];
}
@end
- ViewModel处理View响应事件
#import "MVVMViewModel.h"
#import "FBKVOController.h"
@interface MVVMViewModel ()
@property (nonatomic,weak) MVVModel *model;
@end
@implementation MVVMViewModel
// 初始化ViewModel
-(void)setWithModel:(MVVModel *)model{
self.model = model;
self.contentStr = model.content;
}
// 响应View事件产生
-(void)onPrintClick
{
int rand = arc4random()%10;
self.model.content = [NSString stringWithFormat:@"line %d",rand];
self.contentStr = self.model.content;
}
@end