跳到主要内容

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+)支持编程式路由和深链接,更推荐