SwiftUI 是 Apple 推出的声明式 UI 框架,以下是一些实用技巧和最佳实践,可以帮助你更高效地开发 iOS/macOS/watchOS/tvOS 应用。
1. 布局技巧
灵活的空间占用
swift
// 使用 Spacer 填充可用空间
HStack {
Text("Left")
Spacer() // 填充中间空间
Text("Right")
}
// 使用 frame 控制视图大小
Text("Hello")
.frame(maxWidth: .infinity, maxHeight: .infinity) // 填充父视图
.background(Color.yellow)
条件显示视图
swift
@State private var isShowing = false
var body: some View {
VStack {
if isShowing {
Text("Visible")
} else {
EmptyView()
}
// 或者使用更简洁的方式
isShowing ? Text("Visible") : nil
}
}
2. 状态管理
使用 @State 和 @Binding
swift
struct ParentView: View {
@State private var text = ""
var body: some View {
VStack {
Text("Parent: \(text)")
ChildView(text: $text) // 传递绑定
}
}
}
struct ChildView: View {
@Binding var text: String
var body: some View {
TextField("Enter text", text: $text)
}
}
使用 @ObservedObject 和 @Published
swift
class UserSettings: ObservableObject {
@Published var score = 0
}
struct ContentView: View {
@ObservedObject var settings = UserSettings()
var body: some View {
VStack {
Text("Score: \(settings.score)")
Button("Increase") {
settings.score += 1
}
}
}
}
3. 列表与导航
动态列表
swift
struct ContentView: View {
let items = ["Apple", "Banana", "Cherry"]
var body: some View {
List(items, id: \.self) { item in
Text(item)
}
}
}
带删除和移动功能的列表
swift
struct ContentView: View {
@State private var items = ["Apple", "Banana", "Cherry"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
.onDelete(perform: deleteItems)
.onMove(perform: moveItems)
}
.navigationBarItems(trailing: EditButton())
}
}
func deleteItems(at offsets: IndexSet) {
items.remove(atOffsets: offsets)
}
func moveItems(from source: IndexSet, to destination: Int) {
items.move(fromOffsets: source, toOffset: destination)
}
}
4. 动画与过渡
简单动画
swift
@State private var scale: CGFloat = 1.0
var body: some View {
Button("Tap Me") {
withAnimation(.spring()) {
scale = scale == 1.0 ? 2.0 : 1.0
}
}
.scaleEffect(scale)
}
自定义过渡
swift
@State private var showDetails = false
var body: some View {
VStack {
Button("Toggle") {
withAnimation {
showDetails.toggle()
}
}
if showDetails {
Text("Details")
.transition(.asymmetric(
insertion: .move(edge: .leading),
removal: .move(edge: .trailing)
))
}
}
}
5. 实用修饰符
同时应用多个修饰符
swift
Text("Hello")
.modifier(MyCustomModifier())
// 或者使用扩展
extension View {
func customStyle() -> some View {
self
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
Text("Hello").customStyle()
条件修饰符
swift
@State private var isHighlighted = false
var body: some View {
Text("Hello")
.foregroundColor(isHighlighted ? .red : .blue)
.onTapGesture {
isHighlighted.toggle()
}
}
6. 性能优化
使用 Lazy 视图
swift
ScrollView {
LazyVStack { // 只渲染可见项
ForEach(0..<1000) { index in
Text("Row \(index)")
}
}
}
使用 EquatableView 避免不必要重绘
swift
struct UserView: View, Equatable {
let user: User
var body: some View {
Text(user.name)
}
static func == (lhs: UserView, rhs: UserView) -> Bool {
lhs.user.id == rhs.user.id
}
}
// 使用
UserView(user: someUser).equatable()
- 与其他框架集成
与 UIKit 集成
swift
struct MyUIKitView: UIViewRepresentable {
func makeUIView(context: Context) -> UIActivityIndicatorView {
UIActivityIndicatorView(style: .large)
}
func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
uiView.startAnimating()
}
}
// 使用
MyUIKitView()
与 Core Data 集成
swift
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>
var body: some View {
List {
ForEach(items) { item in
Text("Item at \(item.timestamp!, formatter: itemFormatter)")
}
.onDelete(perform: deleteItems)
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(viewContext.delete)
try? viewContext.save()
}
}
}
8. 调试技巧
调试视图层次结构
swift
Text("Hello")
.debug() // 添加这个修饰符查看视图信息
extension View {
func debug() -> Self {
print(Mirror(reflecting: self).subjectType)
return self
}
}
预览多个设备
swift
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
.previewDevice("iPhone 13")
ContentView()
.previewDevice("iPhone SE (2nd generation)")
ContentView()
.previewDevice("iPad Pro (12.9-inch) (5th generation)")
}
}
}
这些技巧可以帮助你更高效地使用 SwiftUI 构建应用程序。SwiftUI 仍在快速发展,建议定期查看 Apple 的官方文档和 WWDC 会议视频以获取最新信息。