个人理解
还记得舒新峰老师告诉我们做软件的内幕,以前写了一个学生管理系统,有view、persist、serve三个层,是我们第一接触分层设计,以前顶多main函数外写几个函数调用,突然分了三个层,老师说,你设计一个软件,不能只给一个人卖,可以每个人的需求不太一样,但大致是一样的,我们只需要按需求把三个层稍微改改,又能卖给一个人。
这说明了一个问题,三个层次关联并不是很多,在MVC中mode和View甚至不能通信。数据和视图分离,是我们期望MVC能够做到的事。
在iOS中,开始并不好理解,因为我们是从视图开始学习的,在各种Viewcontroller中之间操作,这样对初学者是好的,不用讲点击事件写到controller中,更加方便理解,这样导致controller代码非常复杂,维护成了问题,也导致我一直没有重写View的概念。
开始并不理解重新tabelVIewcell干嘛,我用默认用的好好的。视图与数据的分离,可以让代码易读好维护。
MVC介绍
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
如何写
view和controller分开,以前是写一起的,现在分开,单独写View,然后把View作为controller的属性,model也是作为contrller的属性,controller可以直接通信。
在Viewcontroller中
#import <UIKit/UIKit.h>
#import "LandModel.h"
#import "LoginView.h"
@interface ViewController : UIViewController <PassButtonDelegate>
@property (nonatomic, strong) LandModel *mModel;
@property (nonatomic, strong) LoginView *loginView;
这样controller可以随意的与loginView和model通信
model依靠controller通信
在controller.m文件中
//注册KVO观察者
//model观察loginView的acconttextFieldtext的变化
[self.loginView addObserver:self.mModel forKeyPath:@"accountTextField" options:NSKeyValueObservingOptionNew context:nil];
model作为view的观察者,当view的属性发生变化会激发在model中重写的方法
在model.m中重写了方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
NSLog(@"%@的值已改变", keyPath);
}
model和controller通信
消息通知
一个app有一个默认的消息中心,它负责消息的接受和转发
在controller.m中注册观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(landFail:) name:@"landFail" object:nil];
//controller是一个观察者,也就是说消息会发送给controller
在model.m文件中
下面的这个方法是用于检查俩个字符串的,他们参数的传值方式,是我们接下来要讲的代理传值
- (void)checkNames:(NSString *)username withPassWord:(NSString *)password {
if ([username isEqualToString:@"123"] && [password isEqualToString:@"789"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"landSuccessfule" object:self];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:@"landFail" object:self];
}
}
通过消息中心发出消息,消息名称有俩个,在消息中心注册观察者时,如果写了具体的名称,那么它只能接受这个名称的消息
代理传值
A想做一件事情,但A不方便去做,而B可以,那A委托B去做,B便代理A
生活中,有委托人,被委托人
在View.h文件中
//定义协议与方法
@protocol DeliverDetegate <NSObject>
- (void)setValue:(NSString *)string;
@end
@interface LoginView : UIView
//声明委托变量
@property (weak,nonatomic) id<DeliverDetegate>B_Delegate;
@end
在controller.m中指定view的代理为controller
self.loginView.delegate = self;
实现view的代理方法
如何传值呢
在view.m文件中,在你想要传值的地方
[self.delegate setValue: string];
setValue是你在controller重写的方法,string是传回controller的参数。
在controller.m中重写setValue方法
参数此时就是刚刚传来string
具体代码请看我的github吧
github地址