UIKit - UITableView 무한 스크롤 구현하기
UITableViewDelegate의 scrollViewDidScroll 메서드를 구현하여 ScrollView 하단에 내려왔을 때 다음 페이지의 데이터를 불러오도록 구현함.
BookListViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extension BookListViewController: UITableViewDataSource, UITableViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.height {
bookListManager.fetchNext { result in
switch result{
case .success(_):
DispatchQueue.main.async {
self.tableView.reloadData()
}
case .failure(let error):
print("error : \(error)")
}
}
}
}
}
BookListManager.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import Foundation
final class BookListManager{
private let bookService: BookService = BookService.shared
private var totalPages: Int = 0
private var page: Int = 0
private var size: Int = 10
private var bookList: [BookListResponse] = []
/// 로딩 여부
private var isLoading: Bool = false
/// 마지막 페이지 여부 검증
private var isLastPage: Bool{
page == totalPages - 1
}
/// 책 기록 조회
/// - Parameters:
/// - title: 책 제목
/// - completionHandler: 처리 결과 반환
public func fetch(title: String? = nil, completionHandler: @escaping (Result<PagingResponse<[BookListResponse]>, NetworkingError>) -> Void) {
// 이미 요청이 실행중일 경우 return
guard !isLoading else { return }
page = 0
isLoading = true
bookService.list(page: page, size: size, title: title) { result in
switch result{
case .success(let response):
// 전체 페이지 설정
self.totalPages = response.totalPages
self.bookList = response.content
// 로딩 종료
self.isLoading = false
completionHandler(Result.success(response))
case .failure(let error):
// 실패 시 로딩 종료
self.isLoading = false
completionHandler(Result.failure(error))
}
}
}
/// 다음 페이지 책 기록 조회
/// - Parameters:
/// - title: 책 제목
/// - completionHandler: 처리 결과 반환
public func fetchNext(title: String? = nil, completionHandler: @escaping (Result<PagingResponse<[BookListResponse]>, NetworkingError>) -> Void) {
// 이미 요청 중이거나 마지막 페이지일 경우 return
guard !isLoading, !isLastPage else { return }
let nextPage = page + 1
isLoading = true
bookService.list(page: nextPage, size: size, title: title) { result in
switch result{
case .success(let response):
self.page = nextPage
self.bookList.append(contentsOf: response.content)
self.isLoading = false
completionHandler(Result.success(response))
case .failure(let error):
self.isLoading = false
completionHandler(Result.failure(error))
}
}
}
}
결과
This post is licensed under CC BY 4.0 by the author.
