Infinite Scroll ∞

Duna·2021년 7월 22일
0
post-thumbnail

처음으로 무한 스크롤에 도전장을 내밀었습니다.
무한 스크롤을 위해서 뼈를 갈았습니다. 따흑🥲

일단, 무한 스크롤을 어떻게 구현할까하다가 Scroll 내려서 바닥에 닿을 때마다,

현재 page의 +1한 page값을 서버 Request에 query로 보내서

해당 page의 값에 대한 Response가 들어오면 원래 있던 배열에다가 합쳐주자라는 생각을 했어요.


1️⃣ Page 보내기

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를 매개변수로 넣어뒀어요.

2️⃣ Scroll 끝에 도달 구현

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문안에 있는 코드를 실행하도록 하는거죠!
밑에 도달했을 때 수십개의 다음 페이지 정보를 가져오면 안되니깐요!

3️⃣ 데이터 가져오자

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를 가져와서 서버 연결을 구현해봤습니다.

profile
더 멋진 iOS 개발자를 향해

1개의 댓글

comment-user-thumbnail
2022년 5월 16일

잘 보고 가요!

답글 달기