처음으로 무한 스크롤에 도전장을 내밀었습니다.
무한 스크롤을 위해서 뼈를 갈았습니다. 따흑🥲
일단, 무한 스크롤을 어떻게 구현할까하다가 Scroll 내려서 바닥에 닿을 때마다,
현재 page의 +1한 page값을 서버 Request에 query로 보내서
해당 page의 값에 대한 Response가 들어오면 원래 있던 배열에다가 합쳐주자라는 생각을 했어요.
private func getPopularMovie(page: Int) {
let param: MovieRequest = MovieRequest.init(GeneralAPI.apiKey, "ko", page)
print(param)
authProvider.request(.popular(param: param)) { response in
switch response {
case .success(let result):
do {
self.movieModel = try result.map(MovieModel.self)
self.movieData.append(contentsOf: self.movieModel?.results ?? [])
print("popular movieData 받아옴")
self.movieTableView.reloadData()
} catch(let err) {
print(err.localizedDescription)
}
case .failure(let err):
print(err.localizedDescription)
}
}
}
Parameter에 있는 page값을 scroll할 때마다 갱신하기 위해서 page를 매개변수로 넣어뒀어요.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if movieTableView.contentOffset.y > (movieTableView.contentSize.height - movieTableView.bounds.size.height) {
print("끝에 도달")
if !fetchingMore {
}
}
}
TableView의 contentOffset.y
TableView에 있는 스크롤뷰가 움직이면 ContentOffset이 변합니다.
x는 수평으로 움직일 때 변하고, y는 수직으로 움직일 때 변해요. 우리는 수직으로만 움직이니 y만 가져옵니다!
ContentOffset이 코드에 있는 조건을 충족했다는 건 가장 끝에 도달했다는 걸 의미합니다.
즉, 밑에 닿았다. 닿아버렸다.
!fetchingMore
이건 뭘까 싶을겁니다.
아마 저 상태로 실행을 하게 되면, print문은 !fetchingMore안에 들어가있지 않기 때문에.
"끝에 도달"이 수십개 생기는 걸 볼 수 있을 겁니다.
그래서 fetchingMore를 사용해서 딱 한 번만 저 if문안에 있는 코드를 실행하도록 하는거죠!
밑에 도달했을 때 수십개의 다음 페이지 정보를 가져오면 안되니깐요!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if movieTableView.contentOffset.y > (movieTableView.contentSize.height - movieTableView.bounds.size.height) {
print("끝에 도달")
if !fetchingMore {
beginBatchFetch()
}
}
}
// 위에 코드에 넣어준 모습
private func beginBatchFetch() {
fetchingMore = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: {
self.page += 1
if self.chartMenuButton.isSelected {
self.getPopularMovie(page: self.page)
} else if self.arthouseMenuButton.isSelected {
self.getTopRated(page: self.page)
} else if self.comeoutButton.isSelected {
self.getUpComing(page: self.page)
}
self.fetchingMore = false
self.movieTableView.reloadData()
})
}
fetchingMore를 false로 만들어서 딱 한 번 실행할 수 있도록 했습니다.
beginBatchFetch()를 소개합니다.
DispatchQueue를 사용해서 main스레드에서 비동기적으로 정보들을 가져올 수 있도록 했습니다.
asyncAfter는 실행할 시간(deadline)를 정해두고 실행 코드를 실행합니다(execute).
중간에 있는 if문은(switch로 바꾸면 더 좋지 않을까 생각이 갑자기 드네요)
메뉴 버튼에 따라서 불러와야 하는 라우터가 다르기 때문에 어떤 버튼이 눌렸는가에 따라서 다른 서버를 불러올 수 있도록 해줬습니다.
이 과정을 거치면 맨 위에 있는 .gif처럼 무한 스크롤이 가능해집니다.
Movie API를 가져와서 서버 연결을 구현해봤습니다.
잘 보고 가요!