• 【iOS】MVC



    前言

    MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观

    一、MVC各层职责

    1.1、controller层

    • 生成view,然后组装view
    • 响应View的事件和作为view的代理
    • 处理view的生命周期
    • 处理界面之间的跳转
    • 调用model的数据获取接口,拿到返回数据,处理加工,渲染到view显示

    1.2、model层

    • 业务逻辑封装
    • 提供数据接口给controller使用
    • 数据持久化存储和读取
    • 作为数据模型存储数据

    1.3、view层

    • 界面元素搭建,动画效果,数据展示
    • 接受用户操作并反馈视觉效果

    在这里插入图片描述

    二、总结

    用户点击 View–> 视图响应事件 -->通过代理传递事件到Controller–>发起网络请求更新Model—>Model处理完数据–>代理或通知给Controller–>改变视图样式–>完成

    三、优缺点

    3.1、优点

    通过Controller来控制全局,同时将view和Model的变化分开,对于复杂混乱的项目结构,有了明确的组织方式。

    3.2、缺点

    随着业务逻辑增加,大量的逻辑代码放进了Controller,导致Controller越来越臃肿,后期维护成本高。

    四、代码示例

    我们用一个登录注册小demo来实现我们的MVC框架,首先看一下我们的文件命名:
    在这里插入图片描述
    可以看到笔者的登录注册都分别实现了MVC,这里给出以登录的MVC进行讲解


    Model:

    //
    //  LandModel.h
    //  MVC学习
    //
    //  Created by 夏楠 on 2023/9/9.
    //
    
    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface LandModel : NSObject
    @property(nonatomic, copy)NSMutableArray *accoutArray;
    @property(nonatomic, copy)NSMutableArray *passwordArray;
    - (void)InitLandModel;
    @end
    
    NS_ASSUME_NONNULL_END
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    //
    //  LandModel.m
    //  MVC学习
    //
    //  Created by 夏楠 on 2023/9/9.
    //
    
    #import "LandModel.h"
    
    @implementation LandModel
    - (void)InitLandModel {
        _passwordArray = [[NSMutableArray alloc] init];
        _accoutArray = [[NSMutableArray alloc] init];
    }
    @end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    View:

    //
    //  LandView.h
    //  MVC学习
    //
    //  Created by 夏楠 on 2023/9/9.
    //
    
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface LandView : UIView
    @property(retain, nonatomic)UITextField *textField1;
    @property(retain, nonatomic)UITextField *textField2;
    @property (nonatomic, strong) UIButton *loginBtn;
    @property (nonatomic, strong) UIButton *registeBtn;
    - (void)InitView;
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    //
    //  LandView.m
    //  MVC学习
    //
    //  Created by 夏楠 on 2023/9/9.
    //
    
    #import "LandView.h"
    
    @implementation LandView
    
    - (void)InitView {
        
        //账号
        self.textField1 = [[UITextField alloc]init];
        self.textField1.frame = CGRectMake(60, 350, 280, 40);
        self.textField1.placeholder = @"请输入账号";
        self.textField1.borderStyle = UITextBorderStyleRoundedRect;
        // 设置文本框的圆角
        self.textField1.layer.cornerRadius = self.textField1.bounds.size.height / 2.0;
        self.textField1.layer.masksToBounds = YES;
        self.textField1.backgroundColor = [UIColor whiteColor];  // 设置背景颜色
        self.textField1.layer.borderColor = [UIColor blackColor].CGColor;  // 设置边框颜色
        self.textField1.layer.borderWidth = 1.0;  // 设置边框宽度
        [self.textField1 becomeFirstResponder];
        [self addSubview:self.textField1];
        
        //self.textField1.delegate = self;
    //    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    //    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        //用在Controller层
        
        //密码
        self.textField2 = [[UITextField alloc]init];
        self.textField2.frame = CGRectMake(60, 400, 280, 40);
        self.textField2.placeholder = @"请输入密码";
        self.textField2.borderStyle = UITextBorderStyleRoundedRect;
        // 设置文本框的圆角
        self.textField2.layer.cornerRadius = self.textField2.bounds.size.height / 2.0;
        self.textField2.layer.masksToBounds = YES;
        self.textField2.backgroundColor = [UIColor whiteColor];  // 设置背景颜色
        self.textField2.layer.borderColor = [UIColor blackColor].CGColor;  // 设置边框颜色
        self.textField2.layer.borderWidth = 1.0;  // 设置边框宽度
        self.textField2.secureTextEntry = YES;
        [self.textField2 becomeFirstResponder];
        [self addSubview:self.textField2];
    
    //    self.textField2.delegate = self;
    //    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    //    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        //用在Controller层
    
        _loginBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _loginBtn.frame = CGRectMake(80, 480, 80, 40);
        _loginBtn.layer.cornerRadius = _loginBtn.frame.size.height / 6.0;
        _loginBtn.layer.masksToBounds = YES;
        _loginBtn.layer.borderWidth = 2.0;
        _loginBtn.layer.borderColor = [UIColor whiteColor].CGColor;
        [_loginBtn setTitle:@"登陆" forState:UIControlStateNormal];
        _loginBtn.tintColor = [UIColor blackColor];
        _loginBtn.titleLabel.font = [UIFont systemFontOfSize:20];
        _loginBtn.layer.borderColor = [UIColor blackColor].CGColor;  // 设置边框颜色
        [self addSubview:self.loginBtn];
        
    //    [_loginBtn addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
        //用在controller层
        
        _registeBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _registeBtn.frame = CGRectMake(233, 480, 80, 40);
        _registeBtn.layer.cornerRadius = _registeBtn.frame.size.height / 6.0;
        _registeBtn.layer.masksToBounds = YES;
        _registeBtn.layer.borderWidth = 2.0;
        _registeBtn.layer.borderColor = [UIColor whiteColor].CGColor;
        [_registeBtn setTitle:@"注册" forState:UIControlStateNormal];
        _registeBtn.tintColor = [UIColor blackColor];
        _registeBtn.titleLabel.font = [UIFont systemFontOfSize:20];
        _registeBtn.layer.borderColor = [UIColor blackColor].CGColor;  // 设置边框颜色
        [self addSubview:self.registeBtn];
    
        //添加注册时间
        
    //    [_registeBtn addTarget:self action:@selector(registe) forControlEvents:UIControlEventTouchUpInside];
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    Controller:

    //
    //  ViewController.h
    //  MVC学习
    //
    //  Created by 夏楠 on 2023/9/9.
    //
    
    #import <UIKit/UIKit.h>
    #import "RegistViewController.h"
    #import "LandModel.h"
    #import "LandView.h"
    
    @interface ViewController : UIViewController<UITextFieldDelegate, ConfirmDelegate>
    @property (nonatomic, strong)LandView *landView;
    @property (nonatomic, strong)LandModel *landModel;
    @property (retain, nonatomic)UIAlertController *alert;
    @property (nonatomic, strong)RegistViewController *rVC;
    
    @end
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    //
    //  ViewController.m
    //  MVC学习
    //
    //  Created by 夏楠 on 2023/9/9.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        _landModel = [[LandModel alloc] init];
        [_landModel InitLandModel];
        
        _landView = [[LandView alloc] initWithFrame:self.view.frame];
        [_landView InitView];
        [self.view addSubview:_landView];
        
        [_landView.loginBtn addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
        [_landView.registeBtn addTarget:self action:@selector(registe) forControlEvents:UIControlEventTouchUpInside];
    }
    
    登陆函数
    - (void)login {
    
        int boo1 = 0;
        for (int i = 0; i < _landModel.accoutArray.count; i ++) {
            if ([_landModel.accoutArray[i] isEqualToString:_landView.textField1.text] && [_landModel.passwordArray[i] isEqualToString:_landView.textField2.text]) {
                boo1 = 1;
                break;
            }
        }
    
            if (boo1 == 1) {
                self.alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"登陆成功" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    
                }];
                [self.alert addAction:confirmAction];
                [self presentViewController:self.alert animated:YES completion:nil];
            } else {
                self.alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"用户名或密码错误" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                }];
                [self.alert addAction:confirmAction];
                [self presentViewController:self.alert animated:YES completion:nil];
            }
        }
    
    - (void)registe {
        if (!_rVC)
        _rVC = [[RegistViewController alloc] init];
        _rVC.delegate = self;
        NSLog(@"%@, %@", _landModel.accoutArray, _landModel.passwordArray);
        [self presentViewController:_rVC animated:YES completion:nil];
    }
    
    - (void)confirm:(NSMutableArray *)account password:(NSMutableArray *)password {
        _landModel.accoutArray = [NSMutableArray arrayWithArray:account];
        _landModel.passwordArray = [NSMutableArray arrayWithArray:password];
    }
    
    
    @end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    运行动画:
    在这里插入图片描述


  • 相关阅读:
    Golang学习笔记—结构体
    低代码与数字经济:推动软件开发创新的新引擎
    SpringMVC之文件上传下载以及jrebel的使用
    视频号视频怎么保存到手机,视频号视频怎么保存到手机相册里,苹果手机电脑都可以用
    React基础之Context
    两个list中实体某个属性值相同的实体和不同的实体
    【AUTOSAR-COM】-10.5-APP CAN Frame/PDU“发送周期不准“的影响因素
    Competition Among Parallel Contests(博弈论+机制设计) 论文阅读笔记
    Google推出可连续滚动的移动搜索体验,网友:大可不必
    MFC 使用 TransparentBlt() 在背景图的基础上画东西
  • 原文地址:https://blog.csdn.net/weixin_72437555/article/details/132794591