gpt4 book ai didi

swiftui - 如何在 SwiftUI 中有效过滤长列表?

转载 作者:行者123 更新时间:2023-12-01 08:44:23 25 4
gpt4 key购买 nike

我一直在编写我的第一个 SwiftUI 应用程序,它管理一个图书收藏。它有一个 List大约 3,000 个项目,加载和滚动非常有效。如果使用切换控件过滤列表以仅显示我没有的书籍,则 UI 在更新前会卡住 20 到 30 秒,大概是因为 UI 线程正忙于决定是否显示 3,000 个单元格中的每一个。

在 SwiftUI 中,有没有一种很好的方法来处理像这样的大列表的更新?

var body: some View {
NavigationView {
List {
Toggle(isOn: $userData.showWantsOnly) {
Text("Show wants")
}

ForEach(userData.bookList) { book in
if !self.userData.showWantsOnly || !book.own {
NavigationLink(destination: BookDetail(book: book)) {
BookRow(book: book)
}
}
}
}
}.navigationBarTitle(Text("Books"))
}

最佳答案

您是否尝试过将过滤后的数组传递给 ForEach。像这样的东西:

ForEach(userData.bookList.filter {  return !$0.own }) { book in
NavigationLink(destination: BookDetail(book: book)) { BookRow(book: book) }
}

更新

事实证明,它确实是一个丑陋的、丑陋的错误:

我没有过滤数组,而是在开关翻转时一起删除 ForEach,并用简单的 Text("Nothing") 替换它。看法。结果是一样的,这样做需要30秒!

struct SwiftUIView: View {
@EnvironmentObject var userData: UserData
@State private var show = false

var body: some View {
NavigationView {

List {
Toggle(isOn: $userData.showWantsOnly) {
Text("Show wants")
}

if self.userData.showWantsOnly {
Text("Nothing")
} else {
ForEach(userData.bookList) { book in
NavigationLink(destination: BookDetail(book: book)) {
BookRow(book: book)
}
}
}
}
}.navigationBarTitle(Text("Books"))
}
}

解决方法

我确实找到了一种运行速度很快的解决方法,但它需要一些代码重构。 “魔法”是通过封装发生的。该解决方法强制 SwiftUI 完全丢弃列表,而不是一次删除一行。它通过在两个单独的封装 View 中使用两个单独的列表来实现: FilteredNotFiltered .下面是一个包含 3000 行的完整演示。

import SwiftUI

class UserData: ObservableObject {
@Published var showWantsOnly = false
@Published var bookList: [Book] = []

init() {
for _ in 0..<3001 {
bookList.append(Book())
}
}
}

struct SwiftUIView: View {
@EnvironmentObject var userData: UserData
@State private var show = false

var body: some View {
NavigationView {

VStack {
Toggle(isOn: $userData.showWantsOnly) {
Text("Show wants")
}

if userData.showWantsOnly {
Filtered()
} else {
NotFiltered()
}
}

}.navigationBarTitle(Text("Books"))
}
}

struct Filtered: View {
@EnvironmentObject var userData: UserData

var body: some View {
List(userData.bookList.filter { $0.own }) { book in
NavigationLink(destination: BookDetail(book: book)) {
BookRow(book: book)
}
}
}
}

struct NotFiltered: View {
@EnvironmentObject var userData: UserData

var body: some View {
List(userData.bookList) { book in
NavigationLink(destination: BookDetail(book: book)) {
BookRow(book: book)
}
}
}
}

struct Book: Identifiable {
let id = UUID()
let own = Bool.random()
}

struct BookRow: View {
let book: Book

var body: some View {
Text("\(String(book.own)) \(book.id)")
}
}

struct BookDetail: View {
let book: Book

var body: some View {
Text("Detail for \(book.id)")
}
}

关于swiftui - 如何在 SwiftUI 中有效过滤长列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57637455/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com