SwiftUI异步数据获取 [英] SwiftUI async Data fetch

查看:670
本文介绍了SwiftUI异步数据获取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习SwiftUI并使用电影数据库API创建电影搜索应用

I am trying to learn SwiftUI and creating a movie search app with The movie Database API

一旦滚动到列表的末尾,我想获取新数据.我在List内使用ForEach并检查列表何时到达最后一项,然后执行onAppear()调用,找到了一种可能的解决方案.

I would like to fetch new data once the scroll goes at the end of the List. I found a possible solution on SO using ForEach inside the List and checking when the list reaches the last item and then performing the onAppear() call.

在SwiftUI中,控制事件,即scrollViewDidScroll来检测列表数据的底部

加载第一页后,如何从搜索中加载新页面?

How can I load new pages from the search when the first page has loaded?

您可以在此处找到该项目,该项目太大,无法发布 https://github.com/aspnet82/MovieSearch

You can find the project here, was too big to post https://github.com/aspnet82/MovieSearch

SearchMovieManager->进行调用,我使用了Dispatch.main.async

SearchMovieManager -> Make the fetch call, I used Dispatch.main.async

这是应用程序应该做什么

Here what the app should do

  1. 从API提取数据并显示首页->工作
  2. 当列表"滚动到最后一项时,在下一页上发出另一个读取请求以加载更多数据->这不起作用,它仅适用于请求的第二页.在第二次访存调用之后,它始终显示相同的数据.

我认为问题出在GCD中,但我不知道如何排队处理以使其自动工作

The issue I think is in the GCD, but I do not know how to queue things to make it works automatically

更新:我发现了一种解决方法:

UPDATE: A workaround I found:

List(searchMovieManager.allMovies) { movie in
     Text(movie.title)
}
Text("load more").onTapGesture {
     fetchNextPage(obs: self.searchMovieManager, page: self.searchMovieManager.pageTofetch)
 }

我认为作为解决方案可能还可以,单击该按钮后它会添加新页面,并且在控制数据下载方面也可以吗?

I think might be ok as solution, it adds new page once I tap on the button, and can be also fine in controlling data download maybe?

感谢您的帮助:)

推荐答案

尝试下一个,它使用锚首选项和模拟异步操作的简单模型来向ScrollView(或List)添加一些记录

Try the next, it use anchor preferences and simple model which mimics async operation to add some records to ScrollView (or List)

import SwiftUI

struct PositionData: Identifiable {
    let id: Int
    let center: Anchor<CGPoint>
}

struct Positions: PreferenceKey {
    static var defaultValue: [PositionData] = []
    static func reduce(value: inout [PositionData], nextValue: () -> [PositionData]) {
        value.append(contentsOf: nextValue())
    }
}

struct Data: Identifiable {
    let id: Int
}

class Model: ObservableObject {
    var _flag = false
    var flag: Bool {
        get {
            _flag
        }
        set(newValue) {
            if newValue == true {
                _flag = newValue

                DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                    self._flag = false
                    self.rows += 20
                    print("done")
                }
            }
        }
    }
    @Published var rows = 20
}
struct ContentView: View {
    @ObservedObject var model = Model()
    var body: some View {
        List {
            ForEach(0 ..< model.rows, id:\.self) { i in
                Text("row \(i)").font(.largeTitle).tag(i)
            }
            Rectangle().tag(model.rows).frame(height: 0).anchorPreference(key: Positions.self, value: .center) { (anchor) in
                [PositionData(id: self.model.rows, center: anchor)]
            }.id(model.rows)
        }
        .backgroundPreferenceValue(Positions.self) { (preferences) in
            GeometryReader { proxy in
                Rectangle().frame(width: 0, height: 0).position(self.getPosition(proxy: proxy, tag: self.model.rows, preferences: preferences))
            }
        }
    }
    func getPosition(proxy: GeometryProxy, tag: Int, preferences: [PositionData])->CGPoint {
        let p = preferences.filter({ (p) -> Bool in
            p.id == tag
            })
        if p.isEmpty { return .zero }
        if proxy.size.height - proxy[p[0].center].y > 0 && model.flag == false {
            self.model.flag.toggle()
            print("fetch")
        }
        return .zero
    }
}



struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这是它的样子...

这篇关于SwiftUI异步数据获取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆