在SwiftUI中检测列表底部

efzxgjgh  于 2022-10-04  发布在  Swift
关注(0)|答案(2)|浏览(251)

我知道这个问题可能会被问得很多,我已经看到/尝试了很多答案,但我找不到一个不涉及传统阵列的解决方案。我有一个具有以下结构和示例数据的数据集:

struct Response: Codable {
    let status : String
    let total, startIndex, pageSize, currentPage, pages: Int
    let results: [Result]
}
struct Result: Codable, Identifiable {
    let id, sectionName: String
    let fields: Fields
}
struct Fields: Codable {
    let trailText, bodyText, headline, thumbnail: String
}

示例数据:

{
    "status": "ok",
    "total": 50,
    "startIndex": 1,
    "pageSize": 10,
    "currentPage": 1,
    "pages": 5,
    "results": [
        "id": "random_id1",
        "sectionName": "test",
        "fields": [
            "headline": "test",
            "trailText": "test",
            "bodyText": "test",
            "thumbnail": "test",
        ],
        "id": "random_id3",
        "sectionName": "test",
        "fields": [
            "headline": "test",
            "trailText": "test",
            "bodyText": "test",
            "thumbnail": "test",
        ],
    ]
}

我当前循环遍历列表中的结果以向用户显示信息。一旦用户到达数据的末尾,我想调用一个在(无限滚动)中加载更多数据的API。我不能让它在只加载第一组数据或一次加载所有数据的情况下工作。

我的当前进度仅在最后一行被选中时加载数据,但我希望在最后一行出现时立即加载数据。

class Newsfeed: ObservableObject {

    @Published var data = [Result]()

    func loadData(pageNum: pageNumber) {
        // Do API request here and populate data with result
    }
}

我的视图具有以下结构:

@ObservableObject var newsfeed = Newsfeed()
@State var page: Int = 1 

init() {
    newsfeed.loadData(pageNum: page)
}
var body: some View {
    List {
        ForEach(data) { item in
            Text(item.field.headline)
            Text(item.field.thumbnail)
            Text(item.field.trailText)
            Text(item.field.bodyText)
        }
    }
    .onAppear() {
        if (self.data.last != nil) {
            newsfeed.loadData(pageNum: page + 1)
            self.page += 1
         }
    }
}

我尝试了INDEX方法来检测它当前位于哪一行,然后将其与数据计数进行比较,但INDEX不起作用。

我如何才能检测到已经到达底部并自动加载数据?我的理论是,数据最初有x个元素。当我到达最后一行时,我正在更新数据,使其具有x+x,但是视图没有变化,并且只有在它转到另一个视图并返回时才会更新。

9gm1akwq

9gm1akwq1#

好的,我明白了,我想我调用onAppear太晚了,应该在Foreach内部调用。我必须更改数据模型以使结果和字段都相等,然后您可以执行以下操作:

List {
    ForEach(data) { item in
        Text(item.field.headline)
        Text(item.field.thumbnail)
        Text(item.field.trailText)
        Text(item.field.bodyText)

        .onAppear(){
            if (self.data.last == item){
                newsfeed.loadData(pageNum: page + 1)
                self.page =+ 1
            }
        }
    }
}
lrpiutwd

lrpiutwd2#

我们可以这样做,添加一个页脚作为ProgressView(),当它看起来加载数据时

List {

    Section(footer: ProgressView()
    .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .center)
    .listRowSeparator(.hidden).onAppear(){

    if (self.data.last == item){
           newsfeed.loadData(pageNum: page + 1)
           self.page =+ 1
     }                  
    }){
            ForEach(data) { item in
            Text(item.field.headline)
            Text(item.field.thumbnail)
            Text(item.field.trailText)
            Text(item.field.bodyText)
         }
       }
}

相关问题