跳到主要内容

MVC 与 MVVM

问题

MVC 和 MVVM 的核心区别?MVVM 如何在 iOS 中实践?

答案

Apple MVC

问题:Controller 承担了网络请求、数据转换、业务逻辑、UI 更新等所有职责 → Massive View Controller。

MVVM

ViewModel 不持有 View 引用,不导入 UIKit —— 便于单元测试。

MVVM + Combine 实战

// ViewModel
class UserListViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
@Published var errorMessage: String?

private let service: UserServiceProtocol
private var cancellables = Set<AnyCancellable>()

init(service: UserServiceProtocol = UserService()) {
self.service = service
}

func loadUsers() {
isLoading = true
service.fetchUsers()
.receive(on: DispatchQueue.main)
.sink(
receiveCompletion: { [weak self] completion in
self?.isLoading = false
if case .failure(let error) = completion {
self?.errorMessage = error.localizedDescription
}
},
receiveValue: { [weak self] users in
self?.users = users
}
)
.store(in: &cancellables)
}
}

// View(SwiftUI)
struct UserListView: View {
@StateObject private var vm = UserListViewModel()

var body: some View {
List(vm.users) { user in
Text(user.name)
}
.overlay { if vm.isLoading { ProgressView() } }
.task { vm.loadUsers() }
}
}

常见面试问题

Q1: MVVM 中 ViewModel 可以持有 View 吗?

答案:不可以。ViewModel 不应该 import UIKit/SwiftUI,不应该持有 View 的引用。数据通过绑定(Combine 的 @Published、KVO、闭包)从 ViewModel 流向 View,这是 MVVM 区别于 MVC 的关键。

Q2: Massive ViewController 怎么拆分?

答案

  1. MVVM:抽取数据逻辑到 ViewModel
  2. 子 ViewController:拆分 UI 到嵌套 VC
  3. Extension 分组:按职责拆分到不同 extension
  4. Coordinator:抽离导航逻辑

相关链接