如何使用 MovieDB API Swift 为 TableView 进行分页?

Posted

技术标签:

【中文标题】如何使用 MovieDB API Swift 为 TableView 进行分页?【英文标题】:How to do pagination for a TableView with the MovieDB API Swift? 【发布时间】:2020-10-14 20:17:47 【问题描述】:

我正在尝试创建一个应用程序,用户滚动到表格视图的底部会显示更多结果。目前根据 API 仅显示 20 个项目。 API 有一个页面参数,每次用户通过 ViewController 中的 this 滚动到底部时,我试图将其递增 1。端点https://api.themoviedb.org/3/movie/popular?api_key=API_KEY&language=en-US&page=1

func scrollViewDidScroll(_ scrollView: UIScrollView) 
        let offsetY = scrollView.contentOffset.y

        if offsetY > (tableView.contentSize.height - 100 - scrollView.frame.size.height)
            viewModel.getMovies()  _ in
                DispatchQueue.main.async 
                    self.tableView.reloadData()
                
            
        

在我的 ViewModel 中,我有这些发出请求的函数

    func incrementCurrentPage() -> Int 
        var number = movieDBService.currentPage
        number += 1
        return number
    
    func getMoreMovies(completion: @escaping (Result<Void, Error>) -> Void) 
        let page = incrementCurrentPage()

        getMovies(pageNumber: page)  result in
            switch result 
            case .success():
                completion(.success(()))
            case .failure(let error):
                completion(.failure(error))
            
        
      
func getMovies(pageNumber: Int, completion: @escaping (Result<Void, Error>) -> Void) 

        movieDBService.getPopularMovies(pageNumber: pageNumber)  result in
            switch result 
            case .success(let movie):
                self?.movies = movies.results 
                    completion(.success(()))
            case .failure(let error):
                completion(.failure(error))
            
        
    

在我的服务类中,我有一个属性

 var currentPage: Int = 1

还有一个检索数据的函数


    func getPopularMovies(pageNumber: Int, completion: @escaping (Result<MovieDBModel, Error>) -> Void) 

        let url = constructMovieEndpoint(pageNumber: pageNumber)

        let task = URLSession.shared.dataTask(with: url)  data, response, error in

            guard let response = response else  return 

            guard let data = data else  completion(.failure(.noData))
                return
            

            guard error == nil else  return 

            do 
                let decoder = JSONDecoder()
                let movieData = try decoder.decode(MovieDBModel.self, from: data)
                completion(.success(movieData))
             catch 
                completion(.failure(.decodingError))
            
        
        task.resume()
    

任何帮助将不胜感激。

【问题讨论】:

有什么问题?无法第二次调用 api? 我在getMovies() 中也看到您正在用新数据覆盖moviesself?.movies = movies.results。相反,您应该只添加/附加收到的新数据,以便保留以前的电影记录。类似self?.movies += movies.results 当我向下滚动时,滚动视图锁定并显示已经显示的图像,并且它看起来继续处于生涩状态,因为我认为它正在重新加载。当我向上滚动时,它不显示显示的初始图像。我不确定我是正确地增加页面还是错误地重新加载了 tableview。 我之所以这样做 ``` self?.movi​​es = movies.results`` 是因为最初该数组是空的,我分配了完成处理程序的结果。 是的,但是当数据第二次出现时,不是将新数据添加到您的movies,而是将其替换为新页面电影记录并删除旧的。也许这就是为什么您的 tableview 行为怪异,因为数据源已更改。尝试用我上面告诉的那条线替换这条线。 【参考方案1】:

在 cmets 中回答:

您正在用新数据覆盖电影。

self?.movies = movies.results

相反,您应该只添加/附加收到的新数据,以便保留以前的电影记录。像

self?.movies += movies.results

对于tableview滚动:

延迟是因为您直接从 url 加载的图像。您应该使用SDWebImage 进行异步图片下载。

【讨论】:

以上是关于如何使用 MovieDB API Swift 为 TableView 进行分页?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jquery 对 api 进行 jsonp 调用

如何在 API 调用中设置完成处理程序 - Swift 5

Swift / Instagram API - 如何使用 Instagram 应用进行身份验证

Swift:如何将带有 Alamofilre 或 SwiftyJSON 的 JSON 字符串转换为 ObjectMapper?

如何在 iOS swift 中做产品搜索 api?

如何在 Swift 中解析来自 Alamofire API 的 JSON 响应?