Skip to content

Commit 0a9112f

Browse files
committed
Implemented simple pagination approach to retrieving questions
1 parent d2ea4b0 commit 0a9112f

5 files changed

Lines changed: 46 additions & 14 deletions

File tree

NetworkingInOperations-Example/Data/Managers/Questions/Operations/QuestionsRetrievalOperation.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,25 @@
88

99
import Foundation
1010

11-
class QuestionsRetrievalOperation: ConcurrentOperation<[Question]> {
11+
class QuestionsRetrievalOperation: ConcurrentOperation<QuestionPage> {
1212

1313
private let session: URLSession
1414
private let urlRequestFactory: QuestionsURLRequestFactory
1515
private var task: URLSessionTask?
16+
private let pageIndex: Int
1617

1718
// MARK: - Init
1819

19-
init(session: URLSession = URLSession.shared, urlRequestFactory: QuestionsURLRequestFactory = QuestionsURLRequestFactory()) {
20+
init(pageIndex: Int, session: URLSession = URLSession.shared, urlRequestFactory: QuestionsURLRequestFactory = QuestionsURLRequestFactory()) {
21+
self.pageIndex = pageIndex
2022
self.session = session
2123
self.urlRequestFactory = urlRequestFactory
2224
}
2325

2426
// MARK: - Start
2527

2628
override func start() {
27-
let urlRequest = urlRequestFactory.requestToRetrieveQuestions()
29+
let urlRequest = urlRequestFactory.requestToRetrieveQuestions(pageIndex: pageIndex)
2830

2931
task = session.dataTask(with: urlRequest) { (data, response, error) in
3032
guard let data = data else {
@@ -42,7 +44,7 @@ class QuestionsRetrievalOperation: ConcurrentOperation<[Question]> {
4244
let page = try JSONDecoder().decode(QuestionPage.self, from: data)
4345

4446
DispatchQueue.main.async {
45-
self.complete(result: .success(page.questions))
47+
self.complete(result: .success(page))
4648
}
4749
} catch let error {
4850
DispatchQueue.main.async {

NetworkingInOperations-Example/Data/Managers/Questions/QuestionsDataManager.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class QuestionsDataManager {
2020

2121
// MARK: - Retrieval
2222

23-
func retrievalQuestions(completionHandler: @escaping (_ result: DataRequestResult<[Question]>) -> Void) {
24-
let operation = QuestionsRetrievalOperation()
23+
func retrievalQuestions(pageIndex: Int, completionHandler: @escaping (_ result: DataRequestResult<QuestionPage>) -> Void) {
24+
let operation = QuestionsRetrievalOperation(pageIndex: pageIndex)
2525
operation.completionHandler = completionHandler
2626
queueManager.enqueue(operation)
2727
}

NetworkingInOperations-Example/Data/Models/Question.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,21 @@ private struct DummyCodable: Codable {}
1313
struct QuestionPage: Codable {
1414

1515
let questions: [Question]
16+
let hasMore: Bool
1617

1718
// MARK: - CodingKeys
1819

1920
enum CodingKeys: String, CodingKey {
2021
case questions = "items"
22+
case hasMore = "has_more"
2123
}
2224

2325
// MARK: - Init
2426

2527
init(from decoder: Decoder) throws {
2628
let container = try decoder.container(keyedBy: CodingKeys.self)
2729
questions = try container.decodeArrayByIgnoringInvalidElements(Question.self, forKey: .questions)
30+
hasMore = try container.decode(Bool.self, forKey: .hasMore)
2831
}
2932
}
3033

NetworkingInOperations-Example/Data/Requests/QuestionsURLRequestFactory.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ class QuestionsURLRequestFactory: URLRequestFactory {
1212

1313
// MARK: - Retrieval
1414

15-
func requestToRetrieveQuestions() -> URLRequest {
16-
var request = jsonRequest(endPoint: "questions?order=desc&sort=activity&tagged=ios&pagesize=100&site=stackoverflow")
15+
func requestToRetrieveQuestions(pageIndex: Int) -> URLRequest {
16+
var urlString = "questions?order=desc&sort=activity&tagged=ios&pagesize=30&site=stackoverflow"
17+
18+
if pageIndex != 0 {
19+
urlString += "&page=\(pageIndex)"
20+
}
21+
22+
var request = jsonRequest(endPoint: urlString)
1723
request.httpMethod = HTTPRequestMethod.get.rawValue
1824

1925
return request

NetworkingInOperations-Example/ViewControllers/QuestionsViewController.swift

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ class QuestionsViewController: UIViewController {
1717
fileprivate let questionDataManager = QuestionsDataManager()
1818
fileprivate var questions = [Question]()
1919

20+
fileprivate var pageIndex: Int = 0
21+
fileprivate var retrievingQuestions: Bool = false
22+
fileprivate var hasMoreQuestionsToBeRetrieved: Bool = true
23+
2024
// MARK: - ViewLifecycle
2125

2226
override func viewDidLoad() {
@@ -27,21 +31,29 @@ class QuestionsViewController: UIViewController {
2731
tableView.rowHeight = UITableViewAutomaticDimension
2832
tableView.estimatedRowHeight = 120
2933

30-
retrieveQuestions()
34+
retrieveQuestions(pageIndex: pageIndex)
3135
}
3236

3337
// MARK: - Questions
3438

35-
private func retrieveQuestions() {
39+
private func retrieveQuestions(pageIndex: Int) {
40+
guard retrievingQuestions == false else {
41+
return
42+
}
43+
44+
retrievingQuestions = true
3645
tableView.tableFooterView = loadingFooterView
37-
questionDataManager.retrievalQuestions { (result) in
46+
questionDataManager.retrievalQuestions(pageIndex: pageIndex) { (result) in
3847
self.tableView.tableFooterView = nil
48+
self.retrievingQuestions = false
3949
switch result {
4050
case .failure(let error):
41-
print("Error: \(error)")
51+
print("ERROR: \(error)")
4252
self.tableView.tableFooterView = self.errorFooterView
43-
case .success(let questions):
44-
self.questions = questions
53+
case .success(let page):
54+
self.hasMoreQuestionsToBeRetrieved = page.hasMore
55+
self.pageIndex += 1
56+
self.questions.append(contentsOf: page.questions)
4557
self.tableView.reloadData()
4658
}
4759
}
@@ -67,6 +79,15 @@ extension QuestionsViewController: UITableViewDataSource {
6779

6880
return cell
6981
}
82+
83+
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
84+
let row = indexPath.row
85+
let triggerRetrievalFromLimit = 15
86+
87+
if hasMoreQuestionsToBeRetrieved && (triggerRetrievalFromLimit > (questions.count - row)) {
88+
retrieveQuestions(pageIndex: pageIndex)
89+
}
90+
}
7091
}
7192

7293
// MARK: - UITableViewDelegate

0 commit comments

Comments
 (0)