编程iOS 开发员

在 Swift 中如何实现 MVC(模型-视图-控制器)模式,为什么它至今仍然适用,以及在使用过程中常遇到哪些问题?

用 Hintsage AI 助手通过面试

答案。

问题的历史

模型-视图-控制器(MVC)模式是一种经典的架构模式,早在 Swift 之前就已出现,主要用于分离数据、用户界面和控制逻辑。在 iOS 开发历史上,Apple 将 MVC 宣布为使用 Objective-C 和 Swift 构建应用程序的主要架构模式。

问题

标准 MVC 的主要问题在于,随着时间推移,控制器逐渐成为“庞大的视图控制器”,将业务逻辑、与模型的交互、用户输入处理,甚至显示逻辑都集中到一起。这导致代码的可读性、可重用性和可测试性降低。

解决方案

在 Swift 中,MVC 通过使用 UIViewController 类作为控制器,使用结构体或类作为模型,以及使用 UIView 来构建界面来实现。控制器将模型和视图连接起来,在数据更改时触发界面更新。

代码示例:

struct User { let name: String let age: Int } class UserView: UIView { let nameLabel = UILabel() func display(user: User) { nameLabel.text = "\(user.name), \(user.age) 岁" } } class UserController: UIViewController { var user: User? var userView: UserView! override func loadView() { userView = UserView() view = userView } override func viewDidLoad() { super.viewDidLoad() if let user = user { userView.display(user: user) } } }

关键特性:

  • 通过控制器层连接各个层次。
  • 模型对视图一无所知。
  • 用户输入和导航逻辑在控制器中。

反向提问。

在 MVC 中,视图可以直接依赖于模型吗?

不可以,视图不应直接与模型交互。所有通信仅通过控制器进行;否则,模型会“知道”视图,这违反了责任分离原则,妨碍扩展。

控制器可以包含业务数据和逻辑吗?

人们常常错误地认为控制器可以包含业务逻辑。实际上,业务逻辑应放入模型或单独的服务中,控制器仅应管理视图的生命周期和数据的协调。

如何解决庞大的控制器问题?

为了解决庞大的控制器,将数据处理从控制器转移到模型或服务中,使用代理、委托模式和组合。为视图设置单独的类,或者将显示逻辑直接放入视图中。

常见错误与反模式

  • 模型直接与视图通信
  • 庞大的控制器
  • 在控制器中存储视图状态
  • 没有将业务逻辑提取到模型中

生活中的例子

消极案例

在一个项目中,控制器同时存储用户数据、处理这些数据和显示代码。很难在其他控制器中重用逻辑,测试业务逻辑也非常困难。

优点:

  • 启动速度快,类很少

缺点:

  • 代码可读性差
  • 维护和测试困难

积极案例

模型仅负责数据和业务逻辑,视图负责绘制界面,控制器将它们连接在一起。能够重用组件,更快地测试和扩展应用程序。

优点:

  • 清晰的架构
  • 易于测试
  • 快速开发

缺点:

  • 刚开始时代码稍多,需要在责任分离上自律。