首页 > 解决方案 > List 对象的 SwiftUI 分页

问题描述

我在 SwiftUI 中实现了一个带有搜索栏的列表。现在我想为这个列表实现分页。当用户滚动到列表底部时,应该加载新元素。我的问题是,我怎样才能检测到用户滚动到最后?发生这种情况时,我想加载新元素,附加它们并将它们显示给用户。

我的代码如下所示:

import Foundation
import SwiftUI

struct MyList: View {
    @EnvironmentObject var webService: GetRequestsWebService

    @ObservedObject var viewModelMyList: MyListViewModel

    @State private var query = ""

    var body: some View {

        let binding = Binding<String>(
            get: { self.query },
            set: { self.query = $0; self.textFieldChanged($0) }
        )

        return NavigationView {
            // how to detect here when end of the list is reached by scrolling?
            List {
                // searchbar here inside the list element
                TextField("Search...", text: binding) {
                    self.fetchResults()
                }

                ForEach(viewModelMyList.items, id: \.id) { item in
                    MyRow(itemToProcess: item)
                }
            } 
            .navigationBarTitle("Title")
        }.onAppear(perform: fetchResults)

    }

    private func textFieldChanged(_ text: String) {        
        text.isEmpty ? viewModelMyList.fetchResultsThrottelt(for: nil) : viewModelMyList.fetchResultsThrottelt(for: text)
    }

    private func fetchResults() {
        query.isEmpty ? viewModelMyList.fetchResults(for: nil) : viewModelMyList.fetchResults(for: query)
    }
}

这种情况也有点特殊,因为列表中包含搜索栏。我会感谢任何建议,因为有了这个:)。

标签: iosswiftlistswiftuicombine

解决方案


由于您已经List为搜索栏添加了一个人工行,因此您可以简单地将另一个视图添加到列表中,当它出现在屏幕上时将触发另一个获取(onAppear()按照 Josh 的建议使用)。通过这样做,您不必进行任何“复杂”的计算来知道一行是否是最后一行……人工行总是最后一行!

我已经在我的一个项目中使用了它,但我从未在屏幕上看到过这个元素,因为加载在它出现在屏幕上之前就被触发得如此之快。(您当然可以使用透明/不可见元素,或者甚至可以使用微调器;-))

            List {
                TextField("Search...", text: binding) { /* ... */ }

                ForEach(viewModelMyList.items, id: \.id) { item in
                    // ...
                }

                if self.viewModelMyList.hasMoreRows {
                    Text("Fetching more...")
                        .onAppear(perform: {
                            self.viewModelMyList.fetchMore()
                        })
                }

推荐阅读