零基础也能懂:iOS三大架构MVC、MVVM、VIPER怎么选?

黄文♪
2025-12-21 08:21
阅读 2027

大家好,我是小林,一名985毕业的全栈工程师,也在掘金写了好几年的入门教程。今天这篇教程,是写给那些刚接触iOS开发、听到“架构”两个字就头大的新手朋友的。

我当初学iOS的时候,一上来就被Xcode里默认生成的ViewController吓住了——代码又长又乱,改个按钮逻辑都要翻半天。后来才知道,这其实是MVC架构用得不规范的结果。再往后,我又听说了MVVM、VIPER这些高大上的词,一度以为只有大厂才配用。其实不然!只要理解清楚它们的本质和适用场景,即使是零基础的同学,也能根据项目需求做出合理选择。

所以,我决定写下这篇对比教程,用最直白的语言、最简单的例子,带你搞明白:MVC、MVVM、VIPER到底有什么区别?什么时候该用哪个?


一、为什么需要架构?先搞懂这个问题

想象一下,你要做一顿饭:

  • 如果只是煮个面,你可能直接在锅里下面、加调料,一步到位(就像写一个简单的Demo)。
  • 但如果你要开餐厅,每天做100份不同菜品,就必须分工:有人切菜、有人炒菜、有人洗碗、有人上菜。

iOS应用架构,就是帮你“分工”的规则。 它把代码分成不同角色(比如数据、界面、逻辑),让项目结构清晰、易于维护、方便测试。

没有架构的代码,就像厨房里所有人挤在一起抢锅铲——改一处,崩三处。


二、开发环境准备(超简单)

你只需要:

  1. 一台Mac电脑
  2. 安装最新版 Xcode(App Store免费下载)
  3. 打开Xcode → Create a new Xcode project → 选择 App 模板
  4. 填写 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 exampleios viper sample
书籍 《iOS应用架构谈》(唐巧著)
工具 Xcode 自带的 Refactor 功能(右键 → Refactor → Extract Method)帮你拆分代码

七、下一步怎么学?

  1. 先做个小项目:用MVC写一个待办清单App
  2. 尝试重构:把其中的数据逻辑抽到ViewModel,体验MVVM
  3. 阅读源码:找一个GitHub上标着“MVVM”的开源App,看别人怎么组织代码
  4. 不要追求完美:架构是为了服务项目,不是为了炫技。小项目用MVC+良好分层,完全OK!

最后说一句

我当初也纠结过:“到底该用哪个架构?” 后来明白:没有最好的架构,只有最适合当前项目的架构。

MVC 是你的起点,MVVM 是进阶利器,VIPER 是大型项目的“安全网”。作为初学者,不必一开始就追求复杂设计。先把功能做出来,再慢慢优化结构——这才是工程师的成长路径。

希望这篇教程能帮你少走弯路。如果觉得有用,欢迎在掘金给我点赞关注,我会持续更新更多零基础友好的iOS教程!

📌 记住:代码写得清楚,比写得聪明更重要。

评论 0

最热最新
暂无评论
黄文♪Lv.1
0
影响力
0
文章
0
粉丝