为什么在 Button 中放置一个视图会导致 LazyVGrid 出现严重滞后(错误?)?
Why does putting a view in a Button result in terrible lag on LazyVGrid (bug?)?
这是我的代码。没有按钮,但有一个 onTapGesture,滚动非常流畅。伟大的!但是,如果我将 Text() 视图放在一个按钮中,那么延迟真的非常糟糕,甚至有点悬...
这是简化的代码。在我的实际项目中,我有一个名为 GridCell 的视图,它本质上是一个带有字符串的彩色框。但是,如果我将该视图放在一个按钮中(而不是在 ForEach 中使用按钮并将 GridCell 作为其内容/标签),也会出现滞后。我们应该避免使用 LazyVGrids 中的按钮,还是这是某种错误?
import SwiftUI
let columnCount: Int = 11
let gridSpacing: CGFloat = 1
struct SimpleGridView: View {
@State private var selected: String? = nil
let data = (1...1000).map { "\([=10=])" }
let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
let colCount: CGFloat = CGFloat(columnCount)
var body: some View {
GeometryReader { geo in
ScrollView (showsIndicators: false) {
LazyVGrid(columns: columns, spacing: gridSpacing) {
ForEach(data, id: \.self) { item in
// This code creates lag when scrolling
// Button(action: {
// selected = item
// }) {
// Text(item)
// }
/// This code is fine, apparently.
Text(item)
.onTapGesture(count: 1, perform: {
selected = item
})
}
}
.sheet(item: $selected) { item in // activated on selected item
DetailView(item: item)
}
.padding(.horizontal)
}
}
}
}
struct DetailView: View {
let item: String
var body: some View {
Text(item)
}
}
这看起来像是 SwiftUI 的限制。我遇到了同样的问题,并且找到了解决方法。我尝试使用时间分析器来调查根本问题是什么,但我的调查最终以 SwiftUI 中的缓存问题告终。 HVGrid.lengthAndSpacing
使用了 40% 的计算时间来访问缓存。根据它的名字,我认为 VGrid 在内部使用它来计算每一行的大小,但由于某些原因,它不能很好地与按钮一起使用。
我尝试在叠加层中使用按钮。这样,单个“单元格”的大小是根据视图计算的,然后按钮从视图中获取其大小。好像还行。
因此代码将如下所示:
ForEach(data, id: \.self) { item in
Text(item) // This is the UI of the cell.
.overlay {
Button {
print("Button pressed")
selected = item
} label: {
Color.clear
}
}
}
这是我的代码。没有按钮,但有一个 onTapGesture,滚动非常流畅。伟大的!但是,如果我将 Text() 视图放在一个按钮中,那么延迟真的非常糟糕,甚至有点悬...
这是简化的代码。在我的实际项目中,我有一个名为 GridCell 的视图,它本质上是一个带有字符串的彩色框。但是,如果我将该视图放在一个按钮中(而不是在 ForEach 中使用按钮并将 GridCell 作为其内容/标签),也会出现滞后。我们应该避免使用 LazyVGrids 中的按钮,还是这是某种错误?
import SwiftUI
let columnCount: Int = 11
let gridSpacing: CGFloat = 1
struct SimpleGridView: View {
@State private var selected: String? = nil
let data = (1...1000).map { "\([=10=])" }
let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
let colCount: CGFloat = CGFloat(columnCount)
var body: some View {
GeometryReader { geo in
ScrollView (showsIndicators: false) {
LazyVGrid(columns: columns, spacing: gridSpacing) {
ForEach(data, id: \.self) { item in
// This code creates lag when scrolling
// Button(action: {
// selected = item
// }) {
// Text(item)
// }
/// This code is fine, apparently.
Text(item)
.onTapGesture(count: 1, perform: {
selected = item
})
}
}
.sheet(item: $selected) { item in // activated on selected item
DetailView(item: item)
}
.padding(.horizontal)
}
}
}
}
struct DetailView: View {
let item: String
var body: some View {
Text(item)
}
}
这看起来像是 SwiftUI 的限制。我遇到了同样的问题,并且找到了解决方法。我尝试使用时间分析器来调查根本问题是什么,但我的调查最终以 SwiftUI 中的缓存问题告终。 HVGrid.lengthAndSpacing
使用了 40% 的计算时间来访问缓存。根据它的名字,我认为 VGrid 在内部使用它来计算每一行的大小,但由于某些原因,它不能很好地与按钮一起使用。
我尝试在叠加层中使用按钮。这样,单个“单元格”的大小是根据视图计算的,然后按钮从视图中获取其大小。好像还行。
因此代码将如下所示:
ForEach(data, id: \.self) { item in
Text(item) // This is the UI of the cell.
.overlay {
Button {
print("Button pressed")
selected = item
} label: {
Color.clear
}
}
}