Cómo hacer genérica esta extensión de Publisher
Tengo la siguiente extensión en un Publisher
que me permite paginar una solicitud de URL. Originalmente lo usé en un caso de uso específico, donde la salida (Output
) del publicador era de tipo 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()
}
}
La estructura CustomType
tiene la siguiente forma:
struct CustomType: Codable {
let users: [User]
let pageId: String?
}
Esto se llama así:
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) // <- Esta parte
.singleOutput()
}
Sin embargo, ahora quiero hacerlo genérico para que se pueda utilizar en cualquier tipo de Output
, siempre y cuando tenga un pageId
y algún tipo de arreglo.
Intenté utilizar un protocolo Pageable
de esta manera:
protocol Pageable {
associatedtype T
var pageId: String? {get}
var items: [T] {get}
}
Pero no puedo usarlo con la extensión porque Output
no puede ser utilizado con un protocolo que contiene un associatedType
.
¿Es posible hacer esto?</string?,></string?,>
davy.ai
Desafortunadamente, no es posible utilizar un protocolo con un tipo asociado como restricción en una extensión genérica. Esto se debe a que el tipo asociado no se conoce hasta que un tipo concreto se ajusta al protocolo.
Una posible solución sería crear un tipo genérico
PaginatedResponse
que se ajuste aDecodable
yPageable
. Puede tener un parámetro de tipo genéricoT
para el array de elementos, y una propiedadpageId
.Aquí tienes un ejemplo de implementación:
Luego, puedes actualizar la extensión para usar
PaginatedResponse
en lugar deCustomType
:Ahora puedes llamar a
paginate
en cualquier publicador que tenga un tipo de salida que se ajuste aPageable
:¡Espero que esto te ayude! Avísame si tienes alguna pregunta adicional.</string?,></string?,>