Skip to content

Commit 024df12

Browse files
committed
Replace Combine with async/await on paginated feed loading
1 parent 8f44ddc commit 024df12

File tree

8 files changed

+142
-205
lines changed

8 files changed

+142
-205
lines changed

EssentialApp/EssentialApp/CombineHelpers.swift

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,6 @@ import Foundation
66
import Combine
77
import EssentialFeed
88

9-
public extension Paginated {
10-
init(items: [Item], loadMorePublisher: (() -> AnyPublisher<Self, Error>)?) {
11-
self.init(items: items, loadMore: loadMorePublisher.map { publisher in
12-
return { completion in
13-
publisher().subscribe(Subscribers.Sink(receiveCompletion: { result in
14-
if case let .failure(error) = result {
15-
completion(.failure(error))
16-
}
17-
}, receiveValue: { result in
18-
completion(.success(result))
19-
}))
20-
}
21-
})
22-
}
23-
24-
var loadMorePublisher: (() -> AnyPublisher<Self, Error>)? {
25-
guard let loadMore = loadMore else { return nil }
26-
27-
return {
28-
Deferred {
29-
Future(loadMore)
30-
}.eraseToAnyPublisher()
31-
}
32-
}
33-
}
34-
359
@MainActor
3610
public extension HTTPClient {
3711
typealias Publisher = AnyPublisher<(Data, HTTPURLResponse), Error>

EssentialApp/EssentialApp/FeedUIComposer.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@
33
//
44

55
import UIKit
6-
import Combine
76
import EssentialFeed
87
import EssentialFeediOS
98

109
@MainActor
1110
public final class FeedUIComposer {
1211
private init() {}
1312

14-
private typealias FeedPresentationAdapter = LoadResourcePresentationAdapter<Paginated<FeedImage>, FeedViewAdapter>
13+
private typealias FeedPresentationAdapter = AsyncLoadResourcePresentationAdapter<Paginated<FeedImage>, FeedViewAdapter>
1514

1615
public static func feedComposedWith(
17-
feedLoader: @MainActor @escaping () -> AnyPublisher<Paginated<FeedImage>, Error>,
16+
feedLoader: @MainActor @escaping () async throws -> Paginated<FeedImage>,
1817
imageLoader: @MainActor @escaping (URL) async throws -> Data,
1918
selection: @MainActor @escaping (FeedImage) -> Void = { _ in }
2019
) -> ListViewController {

EssentialApp/EssentialApp/FeedViewAdapter.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class FeedViewAdapter: ResourceView {
1414
private let currentFeed: [FeedImage: CellController]
1515

1616
private typealias ImageDataPresentationAdapter = AsyncLoadResourcePresentationAdapter<Data, WeakRefVirtualProxy<FeedImageCellController>>
17-
private typealias LoadMorePresentationAdapter = LoadResourcePresentationAdapter<Paginated<FeedImage>, FeedViewAdapter>
17+
private typealias LoadMorePresentationAdapter = AsyncLoadResourcePresentationAdapter<Paginated<FeedImage>, FeedViewAdapter>
1818

1919
init(currentFeed: [FeedImage: CellController] = [:], controller: ListViewController, imageLoader: @escaping (URL) async throws -> Data, selection: @escaping (FeedImage) -> Void) {
2020
self.currentFeed = currentFeed
@@ -54,12 +54,12 @@ final class FeedViewAdapter: ResourceView {
5454
return controller
5555
}
5656

57-
guard let loadMorePublisher = viewModel.loadMorePublisher else {
57+
guard let loadMoreAsync = viewModel.loadMore else {
5858
controller.display(feed)
5959
return
6060
}
6161

62-
let loadMoreAdapter = LoadMorePresentationAdapter(loader: loadMorePublisher)
62+
let loadMoreAdapter = LoadMorePresentationAdapter(loader: loadMoreAsync)
6363
let loadMore = LoadMoreCellController(callback: loadMoreAdapter.loadResource)
6464

6565
loadMoreAdapter.presenter = LoadResourcePresenter(

EssentialApp/EssentialApp/SceneDelegate.swift

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
4949

5050
private lazy var navigationController = UINavigationController(
5151
rootViewController: FeedUIComposer.feedComposedWith(
52-
feedLoader: makeRemoteFeedLoaderWithLocalFallback,
52+
feedLoader: loadRemoteFeedWithLocalFallback,
5353
imageLoader: loadLocalImageWithRemoteFallback,
5454
selection: showComments))
5555

@@ -127,22 +127,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
127127
let (data, response) = try await httpClient.get(from: url)
128128
return try FeedItemsMapper.map(data, from: response)
129129
}
130-
131-
private func makeRemoteFeedLoaderWithLocalFallback() -> AnyPublisher<Paginated<FeedImage>, Error> {
132-
Deferred {
133-
Future { completion in
134-
Task.immediate {
135-
do {
136-
let feed = try await self.loadRemoteFeedWithLocalFallback()
137-
completion(.success(feed))
138-
} catch {
139-
completion(.failure(error))
140-
}
141-
}
142-
}
143-
}
144-
.eraseToAnyPublisher()
145-
}
146130

147131
private func loadMoreRemoteFeed(last: FeedImage?) async throws -> Paginated<FeedImage> {
148132
async let cachedItems = try await loadLocalFeed()
@@ -158,38 +142,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
158142
return try await makePage(items: items, last: newItems.last)
159143
}
160144

161-
private func makeRemoteLoadMoreLoader(last: FeedImage?) -> AnyPublisher<Paginated<FeedImage>, Error> {
162-
Deferred {
163-
Future { completion in
164-
Task.immediate {
165-
do {
166-
let feed = try await self.loadMoreRemoteFeed(last: last)
167-
completion(.success(feed))
168-
} catch {
169-
completion(.failure(error))
170-
}
171-
}
172-
}
173-
}
174-
.eraseToAnyPublisher()
175-
}
176-
177-
private func makeRemoteFeedLoader(after: FeedImage? = nil) -> AnyPublisher<[FeedImage], Error> {
178-
let url = FeedEndpoint.get(after: after).url(baseURL: baseURL)
179-
180-
return httpClient
181-
.getPublisher(url: url)
182-
.tryMap(FeedItemsMapper.map)
183-
.eraseToAnyPublisher()
184-
}
185-
186145
private func makeFirstPage(items: [FeedImage]) -> Paginated<FeedImage> {
187146
makePage(items: items, last: items.last)
188147
}
189148

190149
private func makePage(items: [FeedImage], last: FeedImage?) -> Paginated<FeedImage> {
191-
Paginated(items: items, loadMorePublisher: last.map { last in
192-
{ self.makeRemoteLoadMoreLoader(last: last) }
150+
Paginated(items: items, loadMore: last.map { last in
151+
{ @MainActor @Sendable in try await self.loadMoreRemoteFeed(last: last) }
193152
})
194153
}
195154

0 commit comments

Comments
 (0)