iOS 응용 (swift)
[iOS - swift] tableView refresh (상단, 하단 새로고침)
jake-kim
2021. 3. 13. 19:26
cf) 오른쪽 스크롤 바 표출, flashScrollIndicators(): ios-development.tistory.com/341

상단 refresh (with RxCocoa) - UIRefreshControl 사용 (상단에 시스템에서 뿌려주는 로딩 UI 생성)

- 사용: 사용자 입장에서 tableView를 볼 때, 상단 refresh를 사용하는 경우는 tableView의 내용이 변한 경우에 사용
cf) 하단 refresh 사용: tableView를 밑으로 내려서 api로 부터 내용을 더 load하고 싶은 경우 사용 - 사용 방법: `UIRefreshControl` 객체를 선언한 후 이 객체를 tableView의 refreshControl로 등록 후 객체의 isRefreshing 값에 업데이트
- UIRefreshControl() 선언
let refreshControl = UIRefreshControl()
- tableView에 refreshControl객체 등록
refreshControl.endRefreshing() // 초기화 - refresh 종료
tableView.refreshControl = refreshControl
- refreshControl 값이 변경된 경우 (상단 스크롤 한 경우) 이벤트가 들어갈 변수 선언 및 바인딩
let refreshLoading = PublishRelay<Bool>() // ViewModel에 있다고 가정
refreshControl.rx.controlEvent(.valueChanged)
.bind(onNext: { [weak self] _ in
// viewModel.updateDataSource()
// 아래코드: viewModel에서 발생한다고 가정
DispatchQueue.main.asyncAfter(wallDeadline: .now() + 3) { [weak self] in
self?.refreshLoading.accept(true) // viewModel에서 dataSource업데이트 끝난 경우
}
}).disposed(by: bag)
- refreshLoading이 이벤트를 받은 경우 - refershControl의 isRefreshing에 반영
refreshLoading
.bind(to: refreshControl.rx.isRefreshing)
.disposed(by: bag)
하단 Refresh - scrollViewWillBeginDecelerating 델리게이트 이용

scrollViewWillBeginDecelerating
- 의미: 스크롤뷰를 상속받은 tableView는 급격히 스크롤을 할때 잠깐 멈춘다음에 다시 스크롤 되는데, 이 때 scrollViewWillBeginDecelerating 델리게이트 함수가 실행


contentOffset 개념
- contentOffset: UITableView는 UIScrollView를 상속받은것
- content, frame영역 중 frame 영역의 origin과 비교했을때의 content view의 현재 위치

- tableView.contentOffset.y = 100 한 경우, content view의 origin이 100만큼 아래로 이동

- scroll이 dercelerrating될 때 scrollViewWillBeginDecelerating 델리게이트와 contentOffset의 위치를 계산하여 refresh
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
let currentOffset = scrollView.contentOffset.y // frame영역의 origin에 비교했을때의 content view의 현재 origin 위치
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height // 화면에는 frame만큼 가득 찰 수 있기때문에 frame의 height를 빼준 것
// 스크롤 할 수 있는 영역보다 더 스크롤된 경우 (하단에서 스크롤이 더 된 경우)
if maximumOffset < currentOffset {
// viewModel.loadNextPage()
showLoading() // 데이터 로딩 중 표시
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
self?.hideLoading()
}
}
}
* source code: github.com/JK0369/table_view_refresh
* 참고
- developer.apple.com/documentation/uikit/uiscrollview/1619404-contentoffset