零基础也能懂:iOS三大架构MVC、MVVM、VIPER怎么选?
大家好,我是小林,一名985毕业的全栈工程师,也在掘金写了好几年的入门教程。今天这篇教程,是写给那些刚接触iOS开发、听到“架构”两个字就头大的新手朋友的。
我当初学iOS的时候,一上来就被Xcode里默认生成的ViewController吓住了——代码又长又乱,改个按钮逻辑都要翻半天。后来才知道,这其实是MVC架构用得不规范的结果。再往后,我又听说了MVVM、VIPER这些高大上的词,一度以为只有大厂才配用。其实不然!只要理解清楚它们的本质和适用场景,即使是零基础的同学,也能根据项目需求做出合理选择。
所以,我决定写下这篇对比教程,用最直白的语言、最简单的例子,带你搞明白:MVC、MVVM、VIPER到底有什么区别?什么时候该用哪个?
一、为什么需要架构?先搞懂这个问题
想象一下,你要做一顿饭:
- 如果只是煮个面,你可能直接在锅里下面、加调料,一步到位(就像写一个简单的Demo)。
- 但如果你要开餐厅,每天做100份不同菜品,就必须分工:有人切菜、有人炒菜、有人洗碗、有人上菜。
iOS应用架构,就是帮你“分工”的规则。 它把代码分成不同角色(比如数据、界面、逻辑),让项目结构清晰、易于维护、方便测试。
没有架构的代码,就像厨房里所有人挤在一起抢锅铲——改一处,崩三处。
二、开发环境准备(超简单)
你只需要:
- 一台Mac电脑
- 安装最新版 Xcode(App Store免费下载)
- 打开Xcode → Create a new Xcode project → 选择 App 模板
- 填写 Product Name(比如
ArchitectureDemo),Interface 选 Storyboard,Language 选 Swift
✅ 提示:不用勾选 Core Data、Tests 等高级选项,我们从最简开始。
创建完成后,你会看到一个 ViewController.swift 文件和一个 Main.storyboard。这就是我们今天的“实验田”。
三、三大架构核心概念拆解
1. MVC:苹果官方默认的“老大哥”
MVC = Model + View + Controller
- Model:负责数据(比如用户信息、网络请求结果)
- View:负责显示(按钮、标签、图片等UI)
- Controller:负责协调(接收用户操作,更新Model或View)
🎯 关键点:View 和 Model 不能直接通信!必须通过 Controller 中转。
举个栗子:点击按钮显示用户名
// Model
struct User {
let name: String
}
// ViewController(Controller)
class ViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
private var user = User(name: "小林")
override func viewDidLoad() {
super.viewDidLoad()
nameLabel.text = user.name // Controller 把 Model 数据给 View
}
}
✅ 优点:简单直观,Xcode默认支持
❌ 缺点:Controller容易变成“巨无霸”(所有逻辑都塞进去),俗称 Massive View Controller
2. MVVM:更清爽的“数据绑定”模式
MVVM = Model + View + ViewModel
- ViewModel:专门处理业务逻辑,并把Model数据“翻译”成View能用的形式
- View 只负责显示,不直接依赖Model
- 关键技巧:用 属性观察 或 响应式框架(如Combine、RxSwift)实现自动更新
同样的功能,用MVVM怎么写?
// ViewModel
class UserViewModel {
let userName: String
init(user: User) {
self.userName = user.name
}
}
// ViewController(现在只管UI!)
class ViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
private let viewModel = UserViewModel(user: User(name: "小林"))
override func viewDidLoad() {
super.viewDidLoad()
nameLabel.text = viewModel.userName // 直接取ViewModel的数据
}
}
💡 如果用 Combine 实现动态更新(比如用户名变了自动刷新UI):
// ViewModel 中 @Published var userName: String // ViewController 中 viewModel.$userName .sink { [weak self] name in self?.nameLabel.text = name } .store(in: &cancellables)
✅ 优点:Controller瘦身成功!逻辑集中在ViewModel,便于单元测试
❌ 缺点:需要学习响应式编程(不过Swift原生已有Combine)
3. VIPER:模块化程度最高的“企业级”架构
VIPER = View + Interactor + Presenter + Entity + Router
听名字就复杂?别怕,拆开看:
| 组件 | 职责 |
|---|---|
| View | 显示UI,接收用户操作(比如点击) |
| Presenter | 接收View事件,告诉Interactor去干活 |
| Interactor | 处理核心业务逻辑(比如调API、计算) |
| Entity | 纯数据模型(类似MVC中的Model) |
| Router | 负责页面跳转 |
🧩 你可以把它想象成一个“五人小组”:View是前台,Presenter是经理,Interactor是技术员,Entity是资料库,Router是司机。
同样功能,VIPER写法(简化版)
// Entity
struct UserEntity {
let name: String
}
// Interactor
class UserInfoInteractor {
func fetchUser() -> UserEntity {
return UserEntity(name: "小林")
}
}
// Presenter
class UserInfoPresenter {
weak var view: UserInfoViewProtocol?
private let interactor = UserInfoInteractor()
func viewDidLoad() {
let user = interactor.fetchUser()
view?.showUserName(user.name)
}
}
// View(通常是ViewController)
protocol UserInfoViewProtocol: AnyObject {
func showUserName(_ name: String)
}
class ViewController: UIViewController, UserInfoViewProtocol {
@IBOutlet weak var nameLabel: UILabel!
private let presenter = UserInfoPresenter()
override func viewDidLoad() {
super.viewDidLoad()
presenter.view = self
presenter.viewDidLoad()
}
func showUserName(_ name: String) {
nameLabel.text = name
}
}
✅ 优点:职责极度清晰,每个模块可独立测试,适合大型团队协作
❌ 缺点:文件多、代码量大,小项目用它就像“杀鸡用牛刀”
四、实战对比:同一个需求,三种写法
需求:点击按钮,从网络获取用户信息并显示姓名。
为简化,我们用本地模拟数据代替真实网络请求。
✅ MVC 写法(全部塞进ViewController)
class ViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var fetchButton: UIButton!
@IBAction func fetchTapped(_ sender: UIButton) {
// 模拟网络请求
DispatchQueue.global().async {
let userData = ["name": "小林"]
DispatchQueue.main.async {
self.nameLabel.text = userData["name"]
}
}
}
}
❗问题:网络逻辑、UI更新、数据解析全混在一起!
✅ MVVM 写法(逻辑移到ViewModel)
// ViewModel
class UserViewModel {
private let userApi = UserAPI()
func fetchUserName(completion: @escaping (String?) -> Void) {
userApi.fetchUser { user in
completion(user?.name)
}
}
}
// ViewController
class ViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
private let viewModel = UserViewModel()
@IBAction func fetchTapped(_ sender: UIButton) {
viewModel.fetchUserName { [weak self] name in
self?.nameLabel.text = name ?? "未知"
}
}
}
✨ 改进:ViewController只管UI,业务交给ViewModel
✅ VIPER 写法(分工明确)
- View:点击按钮 → 通知Presenter
- Presenter:收到通知 → 让Interactor去取数据
- Interactor:调用API → 返回UserEntity
- Presenter:把Entity转成字符串 → 告诉View显示
- View:更新UILabel
🔍 你会发现:没有任何一行业务逻辑出现在ViewController里!
五、新手常见问题解答
Q1:我是新手,该从哪个架构开始学?
答:从MVC开始! 先理解苹果官方的设计思路,再尝试用MVVM优化。VIPER建议等你做过1-2个完整项目后再接触。
Q2:MVVM一定要用RxSwift吗?
答:不需要! Swift 5.1+ 自带的 Combine 框架已经足够。如果连Combine都觉得难,也可以手动传值(像上面的例子那样)。
Q3:为什么我的MVC项目越来越乱?
答:因为你把太多逻辑放进了ViewController。 尝试把网络请求、数据处理抽成单独的Service或Manager类。
Q4:VIPER是不是太重了?
答:对小项目确实如此。 但它强迫你思考“这个逻辑该放哪”,长期看反而能养成好习惯。
六、学习资源推荐
| 类型 | 推荐内容 |
|---|---|
| 官方文档 | Apple Human Interface Guidelines(了解View职责) |
| 免费教程 | Ray Wenderlich 的 Design Patterns 系列 |
| 开源项目 | GitHub搜索 ios mvvm example、ios viper sample |
| 书籍 | 《iOS应用架构谈》(唐巧著) |
| 工具 | Xcode 自带的 Refactor 功能(右键 → Refactor → Extract Method)帮你拆分代码 |
七、下一步怎么学?
- 先做个小项目:用MVC写一个待办清单App
- 尝试重构:把其中的数据逻辑抽到ViewModel,体验MVVM
- 阅读源码:找一个GitHub上标着“MVVM”的开源App,看别人怎么组织代码
- 不要追求完美:架构是为了服务项目,不是为了炫技。小项目用MVC+良好分层,完全OK!
最后说一句
我当初也纠结过:“到底该用哪个架构?” 后来明白:没有最好的架构,只有最适合当前项目的架构。
MVC 是你的起点,MVVM 是进阶利器,VIPER 是大型项目的“安全网”。作为初学者,不必一开始就追求复杂设计。先把功能做出来,再慢慢优化结构——这才是工程师的成长路径。
希望这篇教程能帮你少走弯路。如果觉得有用,欢迎在掘金给我点赞关注,我会持续更新更多零基础友好的iOS教程!
📌 记住:代码写得清楚,比写得聪明更重要。

评论 0