目录

一、MVC模式概述

二、创建Model层

1. 新建Person模型类

2. 实现Person类

三、重构ViewController

1. 修改ViewController.h

2. 重构ViewController.m

四、MVC组件详解

1. Model(Person类)

2. View(Storyboard中的UI元素)

3. Controller(ViewController)

五、MVC数据流分析

六、MVC最佳实践

七、扩展练习

八、常见问题解答

九、总结

相关推荐


一、MVC模式概述

MVC(Model-View-Controller)是Apple官方推荐的iOS应用架构模式,它将应用程序分为三个核心组件:

  1. Model(模型):负责数据和业务逻辑
  2. View(视图):负责用户界面展示
  3. Controller(控制器):作为中介协调Model和View

二、创建Model层

让我们为上篇教程的App创建一个简单的Model。

1. 新建Person模型类

  1. 右键点击项目导航器中的HelloUIKit文件夹
  2. 选择"New File…"
  3. 选择"Objective-C class",点击Next
  4. 类名输入Person,父类保持NSObject
  5. 点击Create

2. 实现Person类

修改Person.h文件:

#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger tapCount;- (instancetype)initWithName:(NSString *)name;
- (NSString *)greetingMessage;@end

修改Person.m文件:

#import "Person.h"@implementation Person- (instancetype)initWithName:(NSString *)name {self = [super init];if (self) {_name = [name copy];_tapCount = 0;}return self;
}- (NSString *)greetingMessage {return [NSString stringWithFormat:@"%@被点击了%ld次", self.name, (long)self.tapCount];
}@end

三、重构ViewController

现在我们来重构ViewController,使其符合MVC架构。

1. 修改ViewController.h

#import <UIKit/UIKit.h>
#import "Person.h"@interface ViewController : UIViewController@property (nonatomic, strong) Person *user;  // Model
@property (weak, nonatomic) IBOutlet UILabel *helloLabel;  // View
- (IBAction)buttonTapped:(id)sender;  // Controller action@end

2. 重构ViewController.m

#import "ViewController.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// 初始化Modelself.user = [[Person alloc] initWithName:@"iOS开发者"];// 初始化UI状态[self updateUI];
}- (void)updateUI {// 根据Model更新Viewself.helloLabel.text = [self.user greetingMessage];
}- (IBAction)buttonTapped:(id)sender {// 更新Modelself.user.tapCount++;// 根据新Model状态更新View[self updateUI];// 更新按钮状态[sender setTitle:@"再点一次" forState:UIControlStateNormal];// 改变背景色CGFloat hue = (arc4random() % 256 / 256.0);self.view.backgroundColor = [UIColor colorWithHue:hue saturation:0.7 brightness:1.0 alpha:1.0];
}@end

四、MVC组件详解

1. Model(Person类)

  • 包含应用数据和业务逻辑
  • 完全独立于UI
  • 提供数据访问和操作方法
  • 示例中greetingMessage方法封装了消息生成逻辑

2. View(Storyboard中的UI元素)

  • 负责展示数据和接收用户输入
  • 不直接与Model交互
  • 通过IBOutlet暴露给Controller
  • 保持被动,由Controller更新

3. Controller(ViewController)

  • 协调Model和View之间的数据流
  • 职责包括:
    • 初始化Model和View (viewDidLoad)
    • 响应View事件 (buttonTapped:)
    • 更新Model (self.user.tapCount++)
    • 根据Model更新View (updateUI方法)
    • 管理View生命周期

五、MVC数据流分析

  1. 用户点击按钮:View触发buttonTapped:事件
  2. Controller处理
    • 更新Model (tapCount++)
    • 调用updateUI方法
  3. 更新View
    • Controller从Model获取数据
    • Controller更新Label显示

这样实现了单向数据流,各组件职责明确。

六、MVC最佳实践

  1. 保持Model独立

    • Model不应导入UIKit
    • 只包含数据和业务逻辑
  2. 保持View被动

    • View不应直接访问Model
    • 通过Controller更新状态
  3. 避免Massive View Controller

    • 将复杂业务逻辑抽离到Model或独立类
    • 使用updateUI方法集中管理界面更新

七、扩展练习

为了更好理解MVC,尝试以下扩展:

  1. 为Person类添加更多属性(如年龄、职业)
  2. 修改greetingMessage方法返回更丰富的信息
  3. 添加重置按钮,将tapCount归零
  4. 创建SettingsViewController来修改Person的name属性

八、常见问题解答

Q:为什么Model不能直接更新View?
A:这会破坏MVC的分离原则,导致代码难以维护和测试。

Q:所有UI更新都要放在updateUI方法中吗?
A:最佳实践是集中管理UI更新,但对于复杂界面可以按功能拆分多个更新方法。

Q:小型项目也需要严格MVC吗?
A:即使是小型项目,遵守MVC也能提高代码可维护性,建议从一开始就养成好习惯。

九、总结

通过本次重构,你学会了:

  1. 如何创建独立的Model层
  2. 严格分离Model、View和Controller
  3. Controller作为协调者的正确职责
  4. 实现单向数据流
  5. MVC各组件之间的通信方式

MVC是iOS开发的基石,掌握它将为你后续学习更复杂的架构(如MVVM、VIPER)打下坚实基础。

相关推荐

Objective-C UI事件处理全解析-CSDN博客文章浏览阅读1.7k次,点赞68次,收藏56次。本文全面解析iOS应用开发中的UI事件处理机制,涵盖响应者链、触摸事件和手势识别三大核心内容。首先详细介绍了响应者链的工作原理及其构成,包括UIResponder的关键方法。其次讲解了触摸事件处理的基础实现和多点触控技术,并演示了拖拽功能的实现。最后深入解析了UIGestureRecognizer的使用方法,包括系统提供的手势识别器、状态管理以及捏合缩放等高级功能的实现。文章还提供了UIControl事件机制、自定义事件传递等高级技巧,并给出性能优化建议和实用调试方法。 https://shuaici.blog.csdn.net/article/details/148784934让界面活起来:Objective-C中的UI动画实现-CSDN博客文章浏览阅读714次,点赞24次,收藏31次。这篇教程详细介绍了iOS开发中Objective-C实现UI动画的方法。主要内容包括:1.UIView基础动画实现,展示透明度、位置等属性变化的简单API;2.CoreAnimation的核心技术,讲解CALayer属性操作和关键帧动画;3.转场动画和iOS7引入的弹簧动画效果;4.动画性能优化技巧和调试方法;5.综合动画示例和常用代码片段。教程从基础到进阶,全面覆盖iOS动画开发技术,强调在实际应用中应保持动画简洁性、一致性和性能优化,为开发者提供了完整的动画实现解决方案。 https://shuaici.blog.csdn.net/article/details/148784474

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端项目集成lint-staged

lint-staged (lint-staged) 这个插件可以只针对进入git暂存区中的代码进行代码格式检查与修复&#xff0c;极大提升效率&#xff0c;避免扫描整个项目文件&#xff0c;代码风格控制 eslint prettier stylelint 看这两篇文章 前端项目vue3项目集成eslint9.x跟prettier 前端项…

李宏毅genai笔记:模型编辑

0 和post training的区别直接用post training的方法是有挑战的&#xff0c;因为通常训练资料只有一笔而且之后不管问什么问题&#xff0c;都有可能只是这个答案了1 模型编辑的评估方案 reliability——同样的问题&#xff0c;需要是目标答案generalization——问题&#xff08;…

Oracle:union all和union区别

UNION ALL和UNION在Oracle中的主要区别体现在处理重复记录、性能及结果排序上&#xff1a;处理重复记录‌UNION‌&#xff1a;自动去除重复记录&#xff0c;确保最终结果唯一。‌UNION ALL‌&#xff1a;保留所有记录&#xff0c;包括完全重复的行。性能表现‌UNION‌&#xff…

[C#/.NET] 内网开发中如何使用 System.Text.Json 实现 JSON 解析(无需 NuGet)

在实际的企业开发环境中&#xff0c;尤其是内网隔离环境&#xff0c;开发人员经常面临无法使用 NuGet 安装外部包的问题。对于基于 .NET Framework 4.8 的应用&#xff0c;JSON 解析是一个常见的需求&#xff0c;但初始项目中往往未包含任何 JSON 处理相关的程序集。这时&#…

JVM(Java 虚拟机)的介绍

JVM原理JVM 核心架构与工作流程1. 类加载机制&#xff08;Class Loading&#xff09;2. 运行时数据区&#xff08;Runtime Data Areas&#xff09;堆&#xff08;Heap&#xff09;方法区&#xff08;Method Area&#xff09;:元空间&#xff08;Metaspace&#xff09;公共区域虚…

Qt 信号槽的扩展知识

Qt 信号槽的扩展知识一、信号与槽的重载Qt信号与槽的重载问题注意事项示例场景二、一个信号连接多个槽1、直接连接多个槽2、使用lambda表达式连接3、连接顺序控制4、断开特定连接5、自动连接方式三、 多个信号连接一个槽基本连接语法使用QSignalMapper区分信号源&#xff08;Qt…

链表算法之【合并两个有序链表】

目录 LeetCode-21题 LeetCode-21题 将两个升序链表合并成一个新的升序链表并返回 class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {if (list1 null)return list2;if (list2 null)return list1;ListNode dummyHead new ListNode();ListN…

Linux - firewall 防火墙

&#x1f525; 什么是 firewalld&#xff1f;firewalld 是一个动态管理防火墙的守护进程&#xff08;daemon&#xff09;&#xff0c;它提供了一个 D-Bus 接口来管理系统或用户的防火墙规则。与传统的静态 iptables 不同&#xff0c;firewalld 支持&#xff1a;区域&#xff08…

【GESP】C++二级真题 luogu-B4356 [GESP202506 二级] 数三角形

GESP C二级&#xff0c;2025年6月真题&#xff0c;多重循环&#xff0c;难度★✮☆☆☆。 题目题解详见&#xff1a;【GESP】C二级真题 luogu-B4356 [GESP202506 二级] 数三角形 | OneCoder 【GESP】C二级真题 luogu-B4356 [GESP202506 二级] 数三角形 | OneCoderGESP C二级&…

遥感影像岩性分类:基于CNN与CNN-EL集成学习的深度学习方法

遥感影像岩性分类&#xff1a;基于CNN与CNN-EL集成学习的深度学习方法 大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下遥感影像岩性分类&#xff1a;基于CNN与CNN-EL集成学习的深度学习方法。该方法充分利用了多源遥感数据的光谱和空间信息&#xff0c;同时结合…

【STM32 学习笔记】SPI通信协议

SPI通信协议 SPI协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface)&#xff0c;即串行外围设备接口&#xff0c; 是一种高速全双工的通信总线。它被广泛地使用在ADC、LCD等设备与MCU间&#xff0c;要求通讯速率较高的场合。   学习本章时&#xff0c;可与I2C…

Kafka如何做到消息不丢失

一、三种消息传递语义(Message Delivery Semantics):核心是“消息被消费处理的次数” Kafka的三种传递语义本质上描述的是“一条消息从生产到最终被消费者处理完成,可能出现的次数”,这由生产者的消息写入可靠性和消费者的offset提交策略共同决定。 1. At most once(最…

HEVC/H.265 码流分析工具 HEVCESBrowser 使用教程

引言 研究视频编解码的都知道&#xff0c;少不了各类的分析工具助力标准研究和算法开发&#xff0c;目前最出名的流媒体分析工具就是elecard系列&#xff0c;但基于一些原因可能大家用的都比较少。因此&#xff0c;找到合适的码流分析工具才是编解码研究的便捷途径&#xff0c…

量子计算+AI芯片:光子计算如何重构神经网络硬件生态

前言 前些天发现了一个巨牛的人工智能免费学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 量子计算AI芯片&#xff1a;光子计算如何重构神经网络硬件生态 ——2025年超异构计算架构下的万亿参数模型训练革命 产业拐点&a…

linux 4.14 kernel屏蔽arm arch timer的方法

在 ARMv7 架构的单核 CPU 系统中&#xff0c;完全禁用 coretime 时钟中断&#xff08;通常是 ARM 私有定时器中断&#xff09;需要谨慎操作&#xff0c;因为这会导致调度器无法工作&#xff0c;系统可能失去响应。以下是实现方法及注意事项&#xff1a;方法 1&#xff1a;通过 …

[实战]调频(FM)和调幅(AM)信号生成(完整C语言实现)

调频&#xff08;FM&#xff09;和调幅&#xff08;AM&#xff09;信号生成 文章目录调频&#xff08;FM&#xff09;和调幅&#xff08;AM&#xff09;信号生成1. 调频&#xff08;FM&#xff09;和调幅&#xff08;AM&#xff09;信号原理与信号生成调幅&#xff08;AM&#…

【LeetCode 热题 100】21. 合并两个有序链表——(解法一)迭代法

Problem: 21. 合并两个有序链表 题目&#xff1a;将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 文章目录整体思路完整代码时空复杂度时间复杂度&#xff1a;O(M N)空间复杂度&#xff1a;O(1)整体思路 这段代码旨在解决…

力扣 hot100 Day40

23. 合并 K 个升序链表 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 //自己写的垃圾 class Solution { public:ListNode* mergeKLists(vector<ListNode*>& lists) {vector<int…

validate CRI v1 image API for endpoint “unix:///run/containerd/containerd.sock“

1.现象pull image failed: Failed to exec command: sudo -E /bin/bash -c "env PATH$PATH crictl pull 172.23.123.117:8443/kubesphereio/pause:3.9"FATA[0000] validate service connection: validate CRI v1 image API for endpoint "unix:///run/container…

【会员专享数据】2013-2024年我国省市县三级逐月SO₂数值数据(Shp/Excel格式)

之前我们分享过2013-2024年全国范围逐月SO₂栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;!该数据来源于韦晶博士、李占清教授团队发布在国家青藏高原科学数据中心网站上的中国高分辨率高质量近地表空气污染物数据集。很多小伙伴拿到数据后反馈栅格数据不太方便使…