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)