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 怎么拆分?
答案:
- MVVM:抽取数据逻辑到 ViewModel
- 子 ViewController:拆分 UI 到嵌套 VC
- Extension 分组:按职责拆分到不同 extension
- Coordinator:抽离导航逻辑