一. MVC框架的概念
MVC(Model-View-Controller)是一种软件设计模式,用于组织和管理应用程序的代码和逻辑。它将应用程序分为三个主要组件:模型(Model)、视图(View)和控制器(Controller),每个组件负责不同的责任。MVC是cocoa应用良好设计的核心。采用这种模式的好处很多。这些应用程序中的许多对象往往更易于重复使用,其接口往往定义得更好。具有MVC设计的应用程序也比其他应用程序更容易扩展。此外,许多Cocoa技术和架构都基于MVC,并要求您的自定义对象扮演MVC角色之一。
模型对象封装特定于应用程序的数据,并定义操作和处理该数据的逻辑和计算。例如,模型对象可能表示游戏中的角色或地址簿中的联系人。模型对象可能与其他模型对象有一对多关系,因此有时应用程序的模型层实际上是一个或多个对象图。作为应用程序持久状态一部分的大部分数据(无论持久状态存储在文件或数据库中)应在数据加载到应用程序后驻留在模型对象中。因为模型对象表示与特定问题域相关的知识和专业知识,所以它们可以在类似的问题域中重用。理想情况下,模型对象应该与视图对象没有显式连接,视图对象呈现其数据并允许用户编辑该数据。模型对象不应该涉及用户界面和呈现问题。
通信:视图层中创建或修改数据的用户操作通过控制器对象进行通信,并导致创建或更新模型对象。当模型对象更改时(例如,通过网络连接接收到新数据),它会通知控制器对象,控制器对象会更新相应的视图对象。
模型表示应用程序的数据和业务逻辑。 它通常包含数据结构、数据库操作、网络请求和应用程序的核心逻辑。
模型独立于用户界面,可以用于多个视图和控制器。
Model继承自NSObject。
查看对象
视图对象是应用程序中用户可以看到的对象。视图对象知道如何绘制自身,并可以响应用户操作。视图对象的主要目的是显示来自应用程序模型对象的数据,并启用对该数据的编辑。尽管如此,视图对象通常与MVC应用程序中的模型对象分离。
因为您通常重用和重新配置它们,所以视图对象提供了应用程序之间的一致性。UIKit和AppKit框架都提供了视图类的集合,Interface Builder在其库中提供了数十个视图对象。
通信:查看对象通过应用程序的控制器对象了解模型数据的更改,并将用户发起的更改(例如,通过控制器对象在文本字段中输入的文本)传递给应用程序的模型对象。
视图负责展示模型的数据给用户,并处理用户界面的交互。 它通常由用户界面元素(如按钮、标签、图像等)组成。
视图应该尽量保持简单,只负责显示数据,而不包含业务逻辑。
View继承自UIView。
控制器对象
控制器对象充当一个或多个应用程序视图对象与其一个或更多模型对象之间的中介。因此,控制器对象是视图对象了解模型对象变化的管道,反之亦然。控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。
通信:控制器对象解释视图对象中的用户操作,并将新的或更改的数据传输到模型层。当模型对象更改时,控制器对象将新的模型数据传递给视图对象,以便它们可以显示。
控制器作为模型和视图之间的中介,负责协调和管理它们之间的交互。
它接收用户的输入(例如点击按钮、滑动屏幕),更新模型的状态,并将更新的数据反映到视图上。
控制器还处理用户事件(如点击、手势),并触发相应的操作和逻辑。
Controller继承自UIViewController。
二.MVC的使用
这次以登录注册为例:
建好相应的文件
这里我将根视图设置为了LandViewController。
LandModel
LandModel存储的是初始的账号和密码,以及后边注册的账号密码。
//LandModel.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface LandModel : NSObject
@property (nonatomic, strong) NSMutableArray* nameArray;
@property (nonatomic, strong) NSMutableArray* passArray;
- (void) landModelInit;
@end
NS_ASSUME_NONNULL_END
//LandModel.m
#import "LandModel.h"
@implementation LandModel
- (void)landModelInit {
self.nameArray = [[NSMutableArray alloc] init];
[self.nameArray addObject:@"123"];
self.passArray = [[NSMutableArray alloc] init];
[self.passArray addObject:@"123"];
}
@end
LandView
//LandView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface LandView : UIView
@property (nonatomic, strong) UITextField* nameField;
@property (nonatomic, strong) UITextField* passField;
@property (nonatomic, strong) UIButton* landButton;
@property (nonatomic, strong) UIButton* registerButton;
@end
NS_ASSUME_NONNULL_END
//LandView.m
#import "LandView.h"
@implementation LandView
- (instancetype) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
self.backgroundColor= UIColor.whiteColor;
self.nameField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
self.nameField.placeholder = @"请输入用户姓名";
[self addSubview:self.nameField];
self.passField = [[UITextField alloc] initWithFrame:CGRectMake(100, 280, 200, 50)];
self.passField.placeholder = @"请输入密码";
self.passField.secureTextEntry = YES;
[self addSubview:self.passField];
self.landButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.landButton setTitle:@"登录" forState:UIControlStateNormal];
self.landButton.titleLabel.font = [UIFont systemFontOfSize:20];
self.landButton.frame = CGRectMake(150, 400, 50, 30);
[self addSubview:self.landButton];
self.registerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.registerButton setTitle:@"注册" forState:UIControlStateNormal];
self.registerButton.titleLabel.font = [UIFont systemFontOfSize:20];
self.registerButton.frame = CGRectMake(220, 400, 50, 30);
[self addSubview:self.registerButton];
return self;
}
@end
LandViewController
//LandViewController.m
#import "LandViewController.h"
#import "LandModel.h"
#import "LandView.h"
#import "RegisterViewController.h"
#import "nextViewController.h"
@interface LandViewController ()<RegisterViewDelegate>
@property (nonatomic, assign) NSInteger flag;
@property (nonatomic, strong) LandView *landView;
@property (nonatomic, strong) LandModel *landModel;
@end
@implementation LandViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addUI];
}
- (void)addUI {
self.landView = [[LandView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[self.view addSubview:self.landView];
[self.landView.landButton addTarget:self action:@selector(land:) forControlEvents:UIControlEventTouchUpInside];
[self.landView.registerButton addTarget:self action:@selector(registerName:) forControlEvents:UIControlEventTouchUpInside];
self.landModel = [[LandModel alloc] init];
[self.landModel landModelInit];
}
- (void)land:(UIButton*)button {
for (int i = 0; i < self.landModel.nameArray.count; i++) {
if ([self.landView.nameField.text isEqualToString:self.landModel.nameArray[i]] && [self.landView.passField.text isEqualToString:self.landModel.passArray[i]]) {
self.flag = 1;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"登陆成功" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:sure];
[self presentViewController:alert animated:YES completion:nil];
}
}
if (!self.flag) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"输入的账号或用户名有误,请重新输入" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:sure];
[self presentViewController:alert animated:YES completion:nil];
}
self.flag = 0;
}
- (void)registerName:(UIButton*)button {
RegisterViewController *view = [[RegisterViewController alloc] init];
view.modalPresentationStyle = UIModalPresentationFullScreen;
view.delegate = self;
view.nameArray = self.landModel.nameArray;
[self presentViewController:view animated:YES completion:nil];
}
- (void)transName:(NSString *)name andPass:(NSString *)pass {
[self.landModel.nameArray addObject:name];
[self.landModel.passArray addObject:pass];
}
@end
RegisterView
//RegisterView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface RegisterView : UIView
@property (nonatomic, strong) UIButton *back;
@property (nonatomic, strong) UIButton *sure;
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *passTextField;
@property (nonatomic, strong) UITextField *againTextField;
@end
NS_ASSUME_NONNULL_END
//RegisterView.m
#import "RegisterView.h"
@implementation RegisterView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor whiteColor];
self.back = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.back.frame = CGRectMake(50, 100, 50, 40);
[self.back setTitle:@"返回" forState:UIControlStateNormal];
self.back.titleLabel.font = [UIFont systemFontOfSize:20];
[self addSubview:self.back];
self.sure = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.sure.frame = CGRectMake(200, 450, 50, 40);
[self.sure setTitle:@"注册" forState:UIControlStateNormal];
self.sure.titleLabel.font = [UIFont systemFontOfSize:20];
[self addSubview:self.sure];
self.nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
self.nameTextField.placeholder = @"请输入用户名";
[self addSubview:self.nameTextField];
self.passTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 270, 200, 50)];
self.passTextField.placeholder = @"请输入密码";
self.passTextField.secureTextEntry = YES;
[self addSubview:self.passTextField];
self.againTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 340, 200, 50)];
self.againTextField.placeholder = @"请确认密码";
self.againTextField.secureTextEntry = YES;
[self addSubview:self.againTextField];
return self;
}
@end
RegisterController
//RegisterController.h
#import <UIKit/UIKit.h>
#import "RegisterView.h"
#import "RegisterModel.h"
@protocol RegisterViewDelegate <NSObject>
- (void)transName:(NSString*)name andPass:(NSString*)pass;
@end
@interface RegisterViewController : UIViewController
@property (nonatomic, strong) RegisterModel *registerModel;
@property (nonatomic, strong) RegisterView *registerView;
@property (nonatomic, strong) id<RegisterViewDelegate> delegate;
@property (nonatomic, strong) NSMutableArray *nameArray;
@end
//RegisterController.m
#import "RegisterViewController.h"
@interface RegisterViewController ()
@end
@implementation RegisterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addUI];
}
- (void)addUI {
self.view.backgroundColor = [UIColor whiteColor];
self.registerView = [[RegisterView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[self.view addSubview:self.registerView];
[self.registerView.back addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];
[self.registerView.sure addTarget:self action:@selector(sure:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)sure:(UIButton*)button {
if ([self.registerView.nameTextField.text isEqualToString:@""] || [self.registerView.passTextField.text isEqualToString:@""] || [self.registerView.againTextField.text isEqualToString:@""]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"请输入您要注册的账号和密码" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:sure];
[self presentViewController:alert animated:YES completion:nil];
}
for (int i = 0; i < self.nameArray.count; i++) {
if ([self.registerView.nameTextField.text isEqualToString:self.nameArray[i]]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"该账号已被注册,请重新输入账号" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:sure];
[self presentViewController:alert animated:YES completion:nil];
}
}
if ([self.registerView.passTextField.text isEqualToString:self.registerView.againTextField.text]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"注册成功" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[self.delegate transName:self.registerView.nameTextField.text andPass:self.registerView.passTextField.text];
[self dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:sure];
[self presentViewController:alert animated:YES completion:nil];
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"两次输入的密码不一致,请确认输入" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:sure];
[self presentViewController:alert animated:YES completion:nil];
}
}
- (void)back:(UIButton*)button {
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
下面是实现的效果图: