智享教程网
白蓝主题五 · 清爽阅读
首页  > 日常经验

SwiftUI MVVM架构实战:让代码更清晰好维护

为什么选 SwiftUI 搭配 MVVM

最近在做一个记账类的小项目,界面用 SwiftUI 写起来确实快,拖几个 Text 和 Button 就能跑。但数据一复杂,逻辑一多,View 里就开始塞各种状态判断和网络请求,改一处地方,别的功能莫名其妙出问题。后来干脆重构,用了 MVVM 架构代码立马清爽了。

MVVM 把界面(View)和数据逻辑(ViewModel)分开,View 只负责展示和交互响应,所有数据处理交给 ViewModel。这样改 UI 不怕动到逻辑,测试也方便,尤其是团队协作时,前端和逻辑可以并行开发。

基本结构长什么样

拿一个简单的用户信息页面举例。界面要显示用户名、余额,点按钮刷新数据。如果全写在 View 里,onAppear、@State、URLRequest 全混在一起,看得头疼。改成 MVVM 后,View 变得特别干净:

<struct UserInfoView: View {
@StateObject private var viewModel = UserInfoViewModel()

var body: some View {
VStack {
Text(viewModel.username)
.font(.headline)
Text("余额:$" + String(viewModel.balance))
.font(.body)

if viewModel.isLoading {
ProgressView()
}

Button("刷新") {
viewModel.fetchUserInfo()
}
}
.onAppear {
viewModel.fetchUserInfo()
}
}
}>

所有的状态变量、加载标识、网络请求都不在 View 里定义,而是通过 viewModel 暴露出来。View 像个“显示器”,只管怎么呈现。

ViewModel 负责干活

UserInfoViewModel 是真正的执行者,它持有数据,发起请求,处理结果。这里用 @Published 让 View 能自动刷新:

<class UserInfoViewModel: ObservableObject {
@Published var username = ""
@Published var balance = 0.0
@Published var isLoading = false

func fetchUserInfo() {
isLoading = true

// 模拟网络请求
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.username = "张三"
self.balance = 1288.5
self.isLoading = false
}
}
}>

实际项目中,这里会调 API,解析 JSON,可能还要处理错误状态。但 View 完全不用知道细节,只要监听 published 属性变化就行。

好处不止是结构清晰

以前改个字段名,得翻半天代码,现在 ViewModel 一眼就能找到对应逻辑。单元测试也好写,直接测 ViewModel 的方法,不用启动整个界面。比如验证余额格式、检查空数据处理,都可以脱离 SwiftUI 单独跑。

而且团队里设计师改 UI,我这边改数据逻辑,互不干扰。上线前加个新字段,只要 ViewModel 提供,View 接上就完事,不用动核心流程。

刚开始觉得多写个 ViewModel 麻烦,用熟了发现省下来的调试时间、沟通成本,远超这点前期投入。特别是项目变大以后,谁改过哪块代码,日志一查就知道,不至于每次更新都提心吊胆。