0

I'm trying to create an app where the user scrolls to the bottom of the tableview more results are displayed. At present only 20 items are displayed as per the API. The API has a parameter for page which I'm trying to increment by 1 each time the user scrolls to the bottom via this in the ViewController. Endpoint 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()
                }
            }
        }

In my ViewModel I have these functions that make the requests

    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))
            }
        }
    }

In my service class I have a property

 var currentPage: Int = 1

and a function which retrieves the data namely


    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()
    }

Any help would be appreciated.

  • whats the issue? you are not able to call the api for second time? – Keshu R. Oct 14 '20 at 20:23
  • also I see in `getMovies()` you are overriding `movies` with new data. `self?.movies = movies.results`. Instead you should just add/append the new data received so that the previous movie records are preserverd. something like `self?.movies += movies.results` – Keshu R. Oct 14 '20 at 20:27
  • When I scroll down the scrollview locks up and displays images that have already been displayed and it looks continues to be in a jerky state as I think it's reloading. When I scroll up it's not displaying the initial images that were shown. I'm not sure if I'm incrementing the page correctly or reloading the tableview incorrectly. – anonymousSwift Oct 14 '20 at 20:28
  • The reason I do ``` self?.movies = movies.results``` is because initially that array is empty and I assign the result of the completion handler. – anonymousSwift Oct 14 '20 at 20:30
  • yeah but the second time when the data comes then instead of adding the new data to your `movies`, its replacing it with the new page movie records and deletes the old ones. maybe thats why your tableview is behaving weird coz the datasource has been changed. Try replacing the line with the one i told above. – Keshu R. Oct 14 '20 at 20:36
  • Thanks! the behaviour of tableview is much better and when scrolling up the old records are still there. The issue now is when scrolling down the tableview isn't updating with new cells and reusing the same ones. Also when scrolling up it doesn't load the cells quickly I'm assuming it's making another request upon the scroll. What would you recommend ? – anonymousSwift Oct 14 '20 at 20:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/223060/discussion-between-praza24-and-iosarchitect-com). – anonymousSwift Oct 14 '20 at 20:57

1 Answers1

1

As answered in comments:

You are overriding movies with new data.

self?.movies = movies.results

Instead you should just add/append the new data received so that the previous movie records are preserverd. something like

self?.movies += movies.results

For the tableview scroll:

The lag is coz of the images that you are directly loading from url. You should use SDWebImage for asynchronous image downloading.

Keshu R.
  • 5,045
  • 1
  • 18
  • 38