I have the following extension on a Publisher
which allows me to paginate a URL request. I originally used this in a specific use case, where the Output
of the publisher was of type CustomType
.
extension Publisher where Output == CustomType,
Failure == Error {
func paginate(pageIdPublisher: CurrentValueSubject<String?, Never>) -> AnyPublisher<[User], Never> {
return self
.handleEvents(receiveOutput: { response in
if let maxId = response.pageId {
pageIdPublisher.send(maxId)
} else {
pageIdPublisher.send(completion: .finished)
}
})
.reduce([]) { allUsers, response in
return response.users + allUsers
}
.catch { error in
Just([])
}
.eraseToAnyPublisher()
}
}
struct CustomType: Codable {
let users: [User]
let pageId: String?
}
This is called like this:
func loadItem() async throws -> [String] {
let pageIdPublisher = CurrentValueSubject<String?, Never>(nil)
return try await pageIdPublisher
.flatMap { pageId in
urlSession
.publisher(
for: .item(pageId: pageId),
receiveOn: queue
)
}
.paginate(pageIdPublisher: pageIdPublisher) // <- This part
.singleOutput()
}
However, I now want to make it generic so that it can be used on any Output
type, so long as it has a pageId
and some kind of array.
I tried using a protocol Pageable
like this:
protocol Pageable {
associatedtype T
var pageId: String? {get}
var items: [T] {get}
}
But I can't use that with the extension because Output
can't have be used with a protocol that contains an associatedType
.
Is this possible?