模型-视图-控制器(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 中,视图可以直接依赖于模型吗?
不可以,视图不应直接与模型交互。所有通信仅通过控制器进行;否则,模型会“知道”视图,这违反了责任分离原则,妨碍扩展。
控制器可以包含业务数据和逻辑吗?
人们常常错误地认为控制器可以包含业务逻辑。实际上,业务逻辑应放入模型或单独的服务中,控制器仅应管理视图的生命周期和数据的协调。
如何解决庞大的控制器问题?
为了解决庞大的控制器,将数据处理从控制器转移到模型或服务中,使用代理、委托模式和组合。为视图设置单独的类,或者将显示逻辑直接放入视图中。
在一个项目中,控制器同时存储用户数据、处理这些数据和显示代码。很难在其他控制器中重用逻辑,测试业务逻辑也非常困难。
优点:
缺点:
模型仅负责数据和业务逻辑,视图负责绘制界面,控制器将它们连接在一起。能够重用组件,更快地测试和扩展应用程序。
优点:
缺点: