SwiftUI 深入面经
SwiftUI 核心知识
1. 数据流与状态管理
| 属性包装器 | 用途 | 作用域 |
|---|---|---|
@State | 视图私有状态 | 当前视图 |
@Binding | 双向绑定父视图状态 | 父→子 |
@StateObject | 创建并持有 ObservableObject | 当前视图拥有 |
@ObservedObject | 观察外部 ObservableObject | 外部传入 |
@EnvironmentObject | 环境中注入的共享对象 | 整棵子树 |
@Environment | 读取系统环境值(colorScheme 等) | 整棵子树 |
class UserStore: ObservableObject {
@Published var name = "Alice"
@Published var isLoggedIn = false
}
struct ContentView: View {
@StateObject private var store = UserStore()
var body: some View {
NavigationView {
ProfileView()
}
.environmentObject(store)
}
}
2. View 更新机制
- SwiftUI 通过比较
View的值(struct)来决定是否重新渲染 @State变化 → 视图重新body计算 → diff → 更新必要部分- EquatableView:手动实现
Equatable,跳过不必要的重计算 - identity:通过
id(...)或条件视图的位置确定视图标识
3. Swift Data & Core Data 集成
// Swift Data(iOS 17+)
@Model class User {
var name: String
var age: Int
init(name: String, age: Int) { ... }
}
struct UserList: View {
@Query var users: [User]
var body: some View {
List(users) { user in Text(user.name) }
}
}
4. 动画系统
// 隐式动画
withAnimation(.spring(response: 0.3)) {
isExpanded.toggle()
}
// 显式动画(精确控制哪个值动画)
Text("Hello")
.scaleEffect(scale)
.animation(.easeInOut, value: scale)
// matchedGeometryEffect(英雄动画)
@Namespace var hero
Image(...).matchedGeometryEffect(id: "avatar", in: hero)
5. 性能优化
- 避免大 body:拆分子视图,SwiftUI 可精准更新子树
- lazy 容器:
LazyVStack/LazyVGrid— 按需加载 - task / onAppear 加载数据:
.task {}自动绑定到视图生命周期 - Instruments → SwiftUI:查看 body 调用次数和渲染时间
6. UIKit 互操作
// SwiftUI 使用 UIKit 组件
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView { MKMapView() }
func updateUIView(_ view: MKMapView, context: Context) { ... }
}
// UIKit 使用 SwiftUI
let vc = UIHostingController(rootView: ProfileView())
7. 高频面试题
- @StateObject 和 @ObservedObject 的区别?
@StateObject:视图创建并拥有对象,视图刷新不重建@ObservedObject:外部传入,视图刷新可能重建(慎用)
- SwiftUI 如何做列表性能优化?
LazyVStack+ForEach配合id参数精准更新 - 如何处理复杂的视图层级性能? 拆分子视图、使用
EquatableView、避免频繁读取环境值 - NavigationStack vs NavigationView? NavigationStack(iOS 16+)支持编程式路由和深链接,更推荐