UIScrollView의 스크롤이 아래쪽에 닿았을 때를 감지하는 함수 만들기
Posted on 2021-12-01 by GKSRUDTN99
Swift&Xcode
Swift
UIScrollView
RxSwift
UIScrollView의 스크롤이 아래쪽에 닿았을 때를 감지하는 함수 만들기
- 제품 리스트 등을 표시할 때, API 결과값에 Pagination이 적용되어 있는 경우가 있는데,
이런 경우 처음에는 모든 제품을 표시하지 않고 일부 제품만을 받아와서 표시하다가,
사용자가 스크롤을 끝까지 내려서 새로운 제품을 보고자 할 때 다시 API 요청을 보내 아직 로드되지 않은 제품들을 표시하도록 만들 수 있다.
예제코드
- ScrollView가 아직 보여주지 않은 Content의 높이가
from space:
높이보다 작아지면, ControlEvent를 내려보내는 함수이다.
import RxSwift
import RxCocoa
extension Reactive where Base: UIScrollView {
func reachedBottom(from space: CGFloat = 0.0) -> ControlEvent<Void> {
let source = contentOffset.map { contentOffset in
let visibleHeight = self.base.frame.height - self.base.contentInset.top - self.base.contentInset.bottom
let y = contentOffset.y + self.base.contentInset.top
let threshold = self.base.contentSize.height - visibleHeight - space
return y >= threshold
}
.distinctUntilChanged()
.filter { $0 }
.map { _ in () }
return ControlEvent(events: source)
}
}
코드 설명
- RxCocoa의
UIScrollView.contentOffset
을 통해 UIScrollView의 현재 스크롤 위치를 비동기 이벤트로 받아올 수 있다. - 이렇게 받아온 스크롤 위치를 현재 UIScrollView의 ContentSize와 비교하여 스크롤이 아래에 닿았는지 확인한다.
visibleHeight
- 현재 UIScrollView에서 표시되고 있는 높이
- UIScrollView의 크기(frame)에서 상하 여백(Inset)을 빼서 구한다.
y
- 현재 UIScrollView에서 표시되고 있는 좌측 상단 꼭짓점의 y좌표이다.
threshold
- UIScrollView가 표시할 전체 Content의 높이 (self.base.contentSize.height)에서 현재 UIScrollView에서 표시되고 있는 높이(visibleHeight)를 빼면 사용자가 UIScrollView를 끝까지 내렸을 때 표시되는 화면의 좌측 상단 꼭짓점의 y좌표를 구할 수 있다.
- UIScrollView를 끝까지 내리기 전에, 일정 거리만큼 남았을 때 ControlEvent를 내려보내고 싶다면, space 매개변수를 통해 임계점을 더 위쪽에 만들 수 있다.
return y >= threshold
- View의 좌표는 화면 아래로 내려갈수록 증가하므로,
y
변수가threshold
보다 커진다는 말은, 임계점보다 아래로 스크롤이 되었다는 뜻이다. - 이때 방출되는 이벤트는
filter{ $0 }
를 통과하여 ControlEvent가 끝까지 내려간다.
- View의 좌표는 화면 아래로 내려갈수록 증가하므로,
- 마지막
map
은 binding 할 때의 편의를 위한 코드이다.- 저 map이 없다면 매번
scrollView.reachedBottom().map{ _ in ~ }
과 같이 map 안에서_ in
을 써줘야 하기 때문이다.
- 저 map이 없다면 매번