SwiftUI 相关的面试题?
2025-04-22 本文已影响0人
lukyy
基础概念
1. SwiftUI 和 UIKit/AppKit 的主要区别
-
声明式 vs 命令式:SwiftUI 使用声明式语法描述 UI 应该是什么状态(如
Text("Hello")),而 UIKit 需要手动操作对象(如label.text = "Hello")。 - 跨平台:SwiftUI 支持 iOS/macOS/watchOS/tvOS 的共享代码,UIKit 仅限 iOS。
- 实时预览:SwiftUI 提供 Canvas 实时预览,无需编译运行。
2. View协议的作用
View 协议要求实现 var body: some View,定义视图的内容。
所有组件(如 Text、Button)都是值类型的结构体,遵循 View 协议以实现组合式 UI。
3. some View的作用
不透明返回类型(Opaque Return Type)隐藏具体视图类型,避免暴露复杂的泛型链(如 VStack<TupleView<(Text, Button)>>)。
swift func makeView() -> some View { Text("Hello") } // 实际返回类型对调用者透明
4.状态管理的 3 种方式
@State:管理视图私有的可变状态(值类型)。
@Binding:与父视图共享状态(双向绑定)。
@ObservedObject:引用外部符合 ObservableObject 的类型。
class UserData: ObservableObject {
@Published var username = "Guest"
@Published var isLoggedIn = false
}
struct ProfileView: View {
@ObservedObject var userData: UserData
}
5. @Statevs@ObservedObject
@State:用于视图内部简单的值类型(如 Bool、Int),生命周期与视图一致。
@ObservedObject:用于外部复杂数据(如网络服务),不管理生命周期,需外部传递。
布局与样式
6. layoutPriority 的作用
- 调整视图在布局中的优先级(默认 0)。数值越高,优先占用空间。
- 示例:两个
Text在HStack中,优先级高的会先扩展。
7. 固定大小与动态大小
// 固定大小
Text("Fixed").frame(width: 100, height: 100)
// 动态填充剩余空间
Text("Flexible").frame(maxWidth: .infinity)
8. ZStack/HStack/VStack 的区别
-
ZStack:层叠视图(类似 UIKit 的UIView叠加)。 -
HStack/VStack:水平/垂直排列视图。 - 对齐示例:
VStack(alignment: .leading) { Text("Left") } // 左对齐
9. ListvsScrollView
-
List:惰性加载,支持分节、滑动删除,适合大数据。 -
ScrollView:立即加载所有子视图,适合少量内容。
10. 自定义按钮动画
Button("Tap") { /* Action */ }
.buttonStyle(MyButtonStyle())
.animation(.easeInOut, value: isPressed)
struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.scaleEffect(configuration.isPressed ? 0.9 : 1.0)
}
}
数据流与绑定
11. @Binding 示例
-
答案:父子视图共享状态:
// 父视图 @State private var isOn = false ChildView(isOn: $isOn) // 子视图 struct ChildView: View { @Binding var isOn: Bool var body: some View { Toggle("Toggle", isOn: $isOn) } }
12. @StateObjectvs@ObservedObject
-
@StateObject:由视图持有生命周期(首次创建后不会丢失)。 -
@ObservedObject:由外部管理,视图重建时可能重新初始化。
13. Environment 传递全局主题
//定义环境Key
struct ThemeKey: EnvironmentKey {
static let defaultValue: Color = .blue
}
extension EnvironmentValues {
var themeColor: Color {
get { self[ThemeKey.self] }
set { self[ThemeKey.self] = newValue }
}
}
//设置环境值
ContentView().environment(\.themeColor, .red)
// 读取环境值
@Environment(\.themeColor) var color
14. onAppear和onDisappear
onAppear:视图出现在屏幕上时调用(适合加载数据)。
onDisappear:视图消失时调用(适合清理资源)。
高级特性
15. 转场动画示例
if showView {
Text("Hello")
.transition(.opacity.combined(with: .slide))
}
Button("Toggle") { withAnimation { showView.toggle() } }
16. 拖拽功能实现
@State private var offset = CGSize.zero
Circle()
.gesture(
DragGesture()
.onChanged { offset = $0.translation }
.onEnded { _ in offset = .zero }
)
.offset(offset)
17. Canvas 绘制圆形
Canvas { context, size in
let circle = Path(ellipseIn: CGRect(x: 0, y: 0, width: 100, height: 100))
context.fill(circle, with: .color(.blue))
}
18. Core Data 集成
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)])
private var items: FetchedResults<Item>
List(items) { item in
Text(item.name ?? "")
}
.environment(\.managedObjectContext, PersistenceController.shared.container.viewContext)
实战与优化
19. 优化 List 性能
- 使用
Identifiable避免重复计算。 - 分页加载(
onAppear触发加载更多)。 - 替代方案:
LazyVStack+ScrollView(但失去原生List功能)。
20. 跨平台代码示例
#if os(iOS)
NavigationStack { content }
#else
NavigationSplitView { sidebar } detail: { detail }
#endif
附加题答案
-
预览失效的可能原因:
- 代码语法错误。
- 预览设备不匹配(如 macOS 预览 iOS 视图)。
- 依赖的
@Environment未注入。
-
测试 SwiftUI 视图:
- 使用
XCTest测试业务逻辑。 - 第三方库(如
ViewInspector)检查视图层次。
- 使用
这些答案涵盖了从基础到高级的 SwiftUI 知识,可根据面试需求调整深度或扩展代码示例。