【iOS】MVC

news2025/1/20 1:47:32

文章目录

  • 前言
  • 一、MVC各层职责
    • 1.1、controller层
    • 1.2、model层
    • 1.3、view层
  • 二、总结
  • 三、优缺点
    • 3.1、优点
    • 3.2、缺点
  • 四、代码示例


前言

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
//
//  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

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

//
//  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];
    
}

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


//
//  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

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/997214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【交叉熵损失torch.nn.CrossEntropyLoss详解-附代码实现】

CrossEntropyLoss 什么是交叉熵softmax损失计算验证CrossEntropyLoss 输入输出介绍验证代码 什么是交叉熵 交叉熵有很多文章介绍&#xff0c;此处不赘述。只需要知道它是可以衡量真实值和预测值之间的差距的&#xff0c;因而用交叉熵来计算损失的时候&#xff0c;损失是越小越…

【JavaScript手撕代码】new

目录 手写 手写 /* * param {Function} fn 构造函数 * return {*} **/ function myNew(fn, ...args){if(typeof fn ! function){return new TypeError(fn must be a function)}// 先创建一个对象let obj Object.create(fn.prototype)// 通过apply让this指向obj, 并调用执行构…

SHIB去零计划:创新金融未来,打造稳定数字资产新范式

SHIB去零计划&#xff0c;由星火有限公司发起&#xff0c;以区块链去中心化手段解决信任危机&#xff0c;对抗垄断与不公平问题&#xff0c;破解经济制裁&#xff0c;实现稳定数字资产的快速有效、平等互利交易。星火有限公司&#xff0c;一家跨国运营集团&#xff0c;主营业务…

UIStackView入门使用两个问题

项目中横向一排元素&#xff0c;竖向一排元素&#xff0c;可以使用UIStackView。UIStackView的原理不做介绍&#xff0c;这里主要讲两个初次使用容易出现的两个问题。 首先创建一个stackview -(UIStackView*)titleStackView{if(_titleStackView nil){_titleStackView [UISta…

时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化

时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化 目录 时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 北方苍鹰优化算法NGO优化VMD&#xff0c;对其分解层数&#xff0c;惩罚因子数做优化…

绝对的搜索利器

苏生不惑第450 篇原创文章&#xff0c;将本公众号设为星标&#xff0c;第一时间看最新文章。 今天分享几个文件搜索利器&#xff0c;下载地址在公众号苏生不惑后台回复2023909&#xff0c;你的小电影要藏不住了。 首先自然是Everything https://www.voidtools.com/zh-cn/&#…

python DVWAXSSPOC练习

XSS反射性低难度 数据包 GET /dv/vulnerabilities/xss_r/?name%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E HTTP/1.1Host: 10.9.75.161Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…

数据结构与算法-BtreeB+Tree

一&#xff1a;引入 作为一个IT从业者大家对数据库肯定是都知道的&#xff0c;大家应该知道在数据库中有个索引&#xff0c;在一张表中用了索引与不用索引那查找效率简直就是天壤之别&#xff0c;但是大家有没思考过&#xff0c;你经常用的索引是什么样的数据结构呢&#xff1f…

Unity中Shader抓取屏幕并实现扭曲效果

文章目录 前言一、屏幕抓取&#xff0c;在上一篇文章已经写了二、实现抓取后的屏幕扭曲实现思路&#xff1a;1、屏幕扭曲要借助传入 UV 贴图进行扭曲2、传入贴图后在顶点着色器的输入参数处&#xff0c;传入一个 float2 uv : TEXCOORD&#xff0c;用于之后对扭曲贴图进行采样3、…

SAP 创建动态内表

创建动态内表 一、根据表名创建内表 程序代码&#xff1a; "复杂方式 SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. PARAMETERS:p_tab TYPE string. SELECTION-SCREEN END OF BLOCK b1.DATA:lr_struct TYPE REF TO data,lr_table TYPE REF TO data. …

【云原生系列】Docker学习

目录 一、Docker常用命令 1 基础命令 2 镜像命令 2.1 docker images 查看本地主机的所有镜像 2.2 docker search 搜索镜像 2.3 docker pull 镜像名[:tag] 下载镜像 2.4 docker rmi 删除镜像 2.5 docker build 构建镜像 3 容器命令 3.1 如拉取一个centos镜像 3.2 运行…

.env文件详解

.env配置文件 vue会根据 process.env.NODE_ENV 的值&#xff0c;自动加载对应的环境配置文件 .env 全局默认配置文件&#xff0c;在所有的环境中被载入;.env.production 生产环境文件 production;.env.development 开发环境文件 development&#xff1b;.env.test/.env.stagi…

从零开始完整实现-循环神经网络RNN

一 简介 使用 pytorch 搭建循环神经网络RNN&#xff0c;循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一类用于 处理序列数据的神经网络架构。与传统神经网络不同&#xff0c;RNN 具有内部循环结构&#xff0c;可以在处理序列数据时保持状态…

MySQL基础篇:掌握数据库基本操作,轻松上手

查看和指定现有的数据库 mysql> show databases; -------------------- | Database | -------------------- | information_schema | | bjpowernode | | eladmin | | mysql | | performance_schema | | sqlalchemy | | s…

makefile之使用函数wildcard和patsubst

Makefile之调用函数 调用makefile机制实现的一些函数 $(function arguments) : function是函数名,arguments是该函数的参数 参数和函数名用空格或Tab分隔,如果有多个参数,之间用逗号隔开. wildcard函数:让通配符在makefile文件中使用有效果 $(wildcard pattern) 输入只有一个参…

Qt串口基本设置与协议收发

前言 1.一直都想要做一个Qt上位机&#xff0c;趁着这个周末有时间&#xff0c;动手写一下 2.comboBox没有点击的信号&#xff0c;所以做了一个触发的功能 3.Qt的数据类型很奇怪&#xff0c;转来转去的我也搞得很迷糊 4.给自己挖个坑&#xff0c;下一期做一个查看波形的上位…

Java输入-a,-b,geek,-c,888,-d,[hello,world]字符之后,如何将[hello,world]这个不分开

Java输入-a,-b,geek,-c,888,-d,[hello,world]字符之后&#xff0c;如何将[hello,world]这个不分开&#xff1f; 你可以使用命令行参数解析库来处理Java输入中的各个参数。在这种情况下&#xff0c;你可以使用Apache Commons CLI库来解析命令行参数。以下是一个示例代码片段&am…

MATLAB遗传算法求解生鲜货损制冷时间窗碳排放多成本车辆路径规划问题

MATLAB遗传算法求解生鲜货损制冷时间窗碳排放多成本车辆路径规划问题实例 1、问题描述 已知配送中心和需求门店的地理位置,并且已经获得各个门店的需求量。关于送货时间的要求,门店都有规定的时间窗,对于超过规定时间窗外的配送时间会产生相应的惩罚成本。为保持生鲜农产品的…

2023.09.10 学习周报

文章目录 摘要文献阅读1-1 题目1-2 创新点1-3 本文工作2-1 题目2-2 什么是图2-3 图神经网络2-4 信息传递3-1 题目3-2 创新点3-3 本文工作 深度学习1.GNN的构建步骤2.构建图的方法3.GNN的简单样例 总结 摘要 本周阅读了三篇文章&#xff0c;第一篇是基于物理信息深度学习和激光…

【LeetCode题目详解】第九章 动态规划part11 ● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV (day50补)

本文章代码以c为例&#xff01; 一、力扣第123题&#xff1a;买卖股票的最佳时机 III 题目&#xff1a; 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意&#xff1…