Bỏ qua để đến nội dung

LazyVStack và LazyHStack

Chỉ render items visible trên màn hình.

ScrollView {
LazyVStack {
ForEach(0..<10000) { index in
Text("Row \(index)")
.onAppear {
print("Row \(index) appeared")
}
}
}
}
ScrollView(.horizontal) {
LazyHStack {
ForEach(items) { item in
ItemCard(item: item)
}
}
}
ScrollView {
LazyVStack(pinnedViews: [.sectionHeaders]) {
Section {
ForEach(0..<20) { _ in
Text("Item")
}
} header: {
Text("Section 1")
.frame(maxWidth: .infinity)
.background(.white)
}
Section {
ForEach(0..<20) { _ in
Text("Item")
}
} header: {
Text("Section 2")
.frame(maxWidth: .infinity)
.background(.white)
}
}
}
VStack LazyVStack
Render all at once Render on-demand
Small lists Large lists
Không cần ScrollView Cần ScrollView
// ❌ Bad for large lists
VStack {
ForEach(0..<10000) { Text("\($0)") }
}
// ✅ Good for large lists
ScrollView {
LazyVStack {
ForEach(0..<10000) { Text("\($0)") }
}
}
struct InfiniteScrollView: View {
@State private var items = Array(0..<20)
@State private var isLoading = false
var body: some View {
ScrollView {
LazyVStack {
ForEach(items, id: \.self) { item in
Text("Item \(item)")
.onAppear {
if item == items.last {
loadMore()
}
}
}
if isLoading {
ProgressView()
}
}
}
}
func loadMore() {
guard !isLoading else { return }
isLoading = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let newItems = items.count..<(items.count + 20)
items.append(contentsOf: newItems)
isLoading = false
}
}
}

  • LazyVStack - Lazy vertical, cần ScrollView
  • LazyHStack - Lazy horizontal
  • pinnedViews - Sticky headers/footers
  • Dùng cho danh sách dài để tối ưu performance