SwiftUI pagination for List object

rb9*_*b90 3 list ios swift swiftui combine

I've implemented a List with a search bar in SwiftUI. Now I want to implement paging for this list. When the user scrolls to the bottom of the list, new elements should be loaded. My problem is, how can I detect that the user scrolled to the end? When this happens I want to load new elements, append them and show them to the user.

My code looks like this:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

Also a little bit special this case, because the list contains the search bar. I would be thankful for any advice because with this :).

pd9*_*d95 12

由于您已经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()
                        })
                }
Run Code Online (Sandbox Code Playgroud)


Jos*_*ann 8

添加 a.onAppear()MyRow让它用刚刚出现的项目调用 viewModel。然后,您可以检查它是否等于列表中的最后一项,或者是否距列表末尾有 n 项并触发分页。