使用 SwiftUI 加载更多功能

问题描述 投票:0回答:2

我已经将 ScrollView 与 HStack 一起使用,现在我需要在用户最后达到滚动时加载更多数据。

var items: [Landmark]

我已经使用了我正在使用

HStack
ForEach

中添加的项目数组
ScrollView(showsHorizontalIndicator: false) {
    HStack(alignment: .top, spacing: 0) {
        ForEach(self.items) { landmark in
            CategoryItem(landmark: landmark)
        }
    }
}

SwiftUI 中管理更多负载的最佳解决方案是什么,而不使用像 loadmore 按钮这样的自定义操作。

scrollview swiftui hstack
2个回答
11
投票

最好使用 ForEach 和 List 来实现此目的

struct ContentView : View {
    @State var textfieldText: String = "String "
    private let chunkSize = 10
    @State var range: Range<Int> = 0..<1

    var body: some View {
        List {
            ForEach(range) { number in
                Text("\(self.textfieldText) \(number)")
            }
            Button(action: loadMore) {
                Text("Load more")
            }
        }
    }

    func loadMore() {
        print("Load more...")
        self.range = 0..<self.range.upperBound + self.chunkSize
    }
}

在此示例中,每次您按更多加载键,都会增加 State 属性的范围。您可以对 BindableObject 执行相同的操作。 如果您想自动执行此操作,可能您应该阅读有关 PullDownButton 的内容(我不确定它是否适用于 PullUp)

更新: 作为一个选项,您可以通过在最后一个单元格上使用 onAppear 修饰符来下载新项目(在本例中它是一个静态按钮)

var body: some View {
        List {
            ForEach(range) { number in
                Text("\(self.textfieldText) \(number)")
            }
            Button(action: loadMore) {
                Text("")
                }
                .onAppear {
                    DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime(uptimeNanoseconds: 10)) {
                        self.loadMore()
                    }
            }
        }
    }

请记住,该调度是必要的,因为如果没有它,您将收到错误消息“在更新表视图时更新表视图”。您可能可以使用另一种异步方式来更新数据


1
投票

如果您想继续使用带有

Data
而不是
Range
的 List,您可以实现下一个脚本:

struct ContentView: View {

    @State var items: [Landmark]

    var body: some View {
        List {
            ForEach(self.items) { landmark in
                CategoryItem(landmark: landmark)
                   .onAppear {
                      checkForMore(landmark)
                   }
            }
        }
    }

    func checkForMore(_ item: LandMark) {
       guard let item = item else { return }

       let thresholdIndex = items.index(items.endIndex, offsetBy: -5)
        if items.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
           // function to request more data
            getMoreLandMarks()
        }
    }
}

您应该在 ViewModel 中工作并将逻辑与 UI 分开。

感谢 Donny Wals:完整示例

© www.soinside.com 2019 - 2024. All rights reserved.