MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
MVC模式虽然是iOS编程中使用最广泛的模式,但论起复杂程度,MVC模式可以算是众多设计模式之首。通常情况下,MVC模式需要综合使用target-action模式、delegate模式、Notification或KVO模式等。
完成以后应该是这样:
按照MVC的思想,VView中应该写两个textField和两个button(以登陆界面为例),写好后的代码如下:
#import
NS_ASSUME_NONNULL_BEGIN
@interface VView : UIView
@property (nonatomic, strong) UIButton *loadBtn;
@property (nonatomic, strong) UIButton *registerBtn;
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *passTextField;
- (void)InitView; //view初始化
@end
#import "VView.h"
@implementation VView
- (void)InitView {
_loadBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_loadBtn setFrame:CGRectMake(80, 400, 100, 50)];
[_loadBtn setTitle:@"load" forState:UIControlStateNormal];
[_loadBtn setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
[self addSubview:_loadBtn];
_registerBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_registerBtn setFrame:CGRectMake(230, 400, 100, 50)];
[_registerBtn setTitle:@"register" forState:UIControlStateNormal];
[_registerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self addSubview:_registerBtn];
_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];
}
会发现button里没有添加target-action方法,这是因为target-action方法需要设置一个target对象,在这个对象里调用action方法。按照MVC的思想,V里面不进行数据处理,而是要在C里面统一调控由C还是M来处理数据。本例中,我们是在C里面处理,所以我把targe-action方法写到C里面。
按照MVC的思想,M主要用于数据的处理,所以在这个案例中我将存放账号和密码的数组放入M中。
#import
NS_ASSUME_NONNULL_BEGIN
@interface MModel : NSObject
@property (nonatomic, strong) NSMutableArray *nameArr;
@property (nonatomic, strong) NSMutableArray *passArr;
- (void)modelInit;
//- (void)addName:(NSString *)name Pass:(NSString *)pass;
@end
#import "MModel.h"
@implementation MModel
- (void)modelInit {
_nameArr = [[NSMutableArray alloc] init];
_passArr = [[NSMutableArray alloc] init];
[_nameArr addObject:@"123"];
[_passArr addObject:@"456"];
}
接下来就是C了,登陆注册需要使用协议来传值,传值的操作我在这里就不解释了,不懂的朋友可以看看这篇博客,由于我在VView和MModel中定义的方法为实例方法,所以我需要实例化VView和MModel来调用这些方法:
#import
#import "RViewController.h"
#import "VView.h"
#import "MModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface ViewController : UIViewController
@property (nonatomic, strong) VView *myView;
@property (nonatomic, strong) MModel *myModel;
@end
#import "ViewController.h"
#import "newViewController.h"
#import "RViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_myView = [[VView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[_myView InitView];
[_myView.loadBtn addTarget:self action:@selector(pressLoad) forControlEvents:UIControlEventTouchUpInside];
[_myView.registerBtn addTarget:self action:@selector(pressRegister) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_myView];
_myModel = [[MModel 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 {
RViewController *RegistViewController = [[RViewController 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];
}
到这里登陆界面就写完了,注册界面原理和它一样,我就只放代码不进行过多的讲解了
因为没有数据的改变,所以RModel里没有任何东西
#import
NS_ASSUME_NONNULL_BEGIN
@interface RModel : NSObject
@end
NS_ASSUME_NONNULL_END
#import "RModel.h"
@implementation RModel
@end
RView:
#import
NS_ASSUME_NONNULL_BEGIN
@interface RView : UIView
@property (nonatomic, strong) UIButton *loadBtn;
@property (nonatomic, strong) UIButton *registerBtn;
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *passTextField;
- (void)InitView; //view初始化
@end
#import "RView.h"
@implementation RView
- (void)InitView {
_loadBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_loadBtn setFrame:CGRectMake(80, 400, 100, 50)];
[_loadBtn setTitle:@"back" forState:UIControlStateNormal];
[_loadBtn setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
[self addSubview:_loadBtn];
_registerBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_registerBtn setFrame:CGRectMake(230, 400, 100, 50)];
[_registerBtn setTitle:@"Ok" forState:UIControlStateNormal];
[_registerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self addSubview:_registerBtn];
_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];
}
RViewController:
#import
#import "RView.h"
#import "RModel.h"
NS_ASSUME_NONNULL_BEGIN
@protocol RegisterDelegate
- (void)passName:(NSString *)name passPass:(NSString *)pass;
@end
@interface RViewController : UIViewController
@property (nonatomic, strong) RView *myView;
@property (nonatomic, strong) RModel *myModel;
@property id registerDelegate;
@end
#import "RViewController.h"
#import "ViewController.h"
@interface RViewController ()
@end
@implementation RViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_myView = [[RView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[_myView InitView];
[_myView.loadBtn addTarget:self action:@selector(pressLoad) forControlEvents:UIControlEventTouchUpInside];
[_myView.registerBtn addTarget:self action:@selector(pressRegister) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_myView];
_myModel = [[RModel 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 *sure) {
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];
}