我有一個LazyVStack我只想更新一個視圖,而不是在螢屏上重新加載所有其他視圖。對于更復雜的單元格,這會導致巨大的性能損失。我已經包含了示例代碼
import SwiftUI
struct ContentView: View {
@State var items = [String]()
var body: some View {
ScrollView {
LazyVStack {
ForEach(self.items, id: \.self) { item in
Button {
if let index = self.items.firstIndex(where: {$0 == item}) {
self.items[index] = "changed \(index)"
}
} label: {
cell(text: item)
}
}
}
}
.onAppear {
for _ in 0...200 {
self.items.append(NSUUID().uuidString)
}
}
}
}
struct cell: View {
let text: String
init(text: String) {
self.text = text
print("init cell", text)
}
var body: some View {
Text(text)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
正如您所看到的,即使只更改 1 個單元格,也會為每個單元格呼叫 init。有沒有辦法避免這種情況?
uj5u.com熱心網友回復:
這是一個有效的代碼,有幾點需要提及,SwiftUI 中的 View 會在這里和那里或 SwiftUI 認為需要的任何時候初始化!但是,如果 body 中的某些值確實發生了變化,則會計算 View 的 body。它計劃像那樣作業,也有一些例外。就像 body 被計算一樣,即使 body 中使用的值和以前一樣沒有變化,我不想討論那個話題!但是在您的示例和您的問題中,我們希望 SwiftUI 僅呈現更改后的視圖,對于此目標,向下代碼運行良好,沒有問題,但是正如您所看到的,我使用了 VStack,如果我們更改VStack為LazyVStack, SwiftUI 會因為它的臥底代碼渲染一些額外的視圖,如果你向下滾動然后向上滾動,它會忘記記憶體中的所有渲染視圖和資料,它會嘗試渲染舊的渲染視圖,所以這就是LazyVStack,我們對此無能為力。蘋果想要LazyVStack懶惰。但是你可以看到這LazyVStack不會渲染所有視圖,但其中一些需要作業。我們不能說或知道有多少視圖以 Lazy 方式渲染,但肯定不是全部。
let initializingArray: () -> [String] = {
var items: [String] = [String]()
for _ in 0...200 { items.append(UUID().uuidString) }
return items
}
struct ContentView: View {
@State var items: [String] = initializingArray()
var body: some View {
ScrollView {
VStack {
ForEach(items, id: \.self) { item in
Button(action: {
if let index = self.items.firstIndex(where: { $0 == item }) {
items[index] = "changed \(index)"
}
}, label: {
ItemView(item: item)
})
}
}
}
}
}
struct ItemView: View {
let item: String
var body: some View {
print("Rendering row for:", item)
return Text(item)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/390829.html
