开发iOS应用时,用SwiftUI写界面越来越普遍。一开始代码可能很清爽,但随着功能增加,视图逻辑变复杂,页面臃肿、状态混乱、重复代码多的问题就冒出来了。这时候就得动手重构,不然改个按钮颜色都得翻三层嵌套。
视图拆分:别让一个文件写满200行
常见情况是,一个ContentView里塞了整个页面,从导航栏到列表再到弹窗全堆在一起。这种结构不仅难读,还容易误改。把大视图拆成小部件是最直接的解法。比如用户资料页,可以把头像区域、信息卡片、操作按钮分别封装成独立的View。
struct ProfileHeader: View {
var body: some View {
VStack {
Image("avatar")
.resizable()
.frame(width: 80, height: 80)
.clipShape(Circle())
Text("张三")
.font(.headline)
}
}
}
这样主页面只需要调用ProfileHeader(),逻辑清晰,复用也方便。
状态管理混乱?别滥用@State
新手常把所有数据都用@State声明,结果父子视图传值时出现双份状态,改一个另一边不更新。这种情况应该把共享状态提升到共同的父级,或者使用@Binding传递引用。
struct ToggleRow: View {
@Binding var isOn: Bool
var body: some View {
HStack {
Text("夜间模式")
Spacer()
Toggle("", isOn: $isOn)
}
}
}
父视图传值时用$darkMode而不是darkMode,确保绑定的是状态本身。
逻辑外移:别在View里写网络请求
有些人在onAppear里直接写URLSession调用,调试时一刷新就卡住。正确的做法是把数据获取逻辑移到独立的ViewModel中,用@ObservedObject关联。
class PostViewModel: ObservableObject {
@Published var posts: [Post] = []
func fetch() async {
// 网络请求逻辑
}
}
View只负责展示和触发,不掺和具体实现,出问题也容易定位是界面还是数据的问题。
预览卡顿?清理不必要的重绘
SwiftUI依赖值类型和属性包装器自动刷新,但有时候一个小状态变化导致整个页面重建。可以用EquatableView或拆分子视图配合@Bindable减少刷新范围。另外,避免在body里做计算操作,比如:
// 别这么写
Text("总价:\(items.map(\$0.price).reduce(0, +))")
应该提前算好存在ViewModel里,View只取结果。
命名规范也属于重构
函数叫buttonAction1、tempFlag,过两周自己都看不懂。重构时顺手改名,比如handleLogoutTap、showConfirmationDialog,别人看代码不用猜意图。文件名也一样,别全叫View1.swift,按功能命名更省时间。
代码重构不是一次性任务,而是日常维护的一部分。每次加功能前花几分钟看看现有结构能不能优化,比后期推倒重来划算得多。