Search code examples
iosswiftcombine

unable to map model from one type to aother with Combine in Swift


I have following code in Repository:

public final class TimeTableRepository: TimeTableRepositoryProtocol {
    private let timeTableRemoteDataSource: TimeTableRemoteDataSource
    
    init(timeTableRemoteDataSource: TimeTableRemoteDataSource) {
        self.timeTableRemoteDataSource = timeTableRemoteDataSource
    }
    
    func getTimeTable() -> AnyPublisher<[TimeTableEntity]?, Error> {
        timeTableRemoteDataSource.getTimeTable().flatMap { return $0.toDomain() }
    }
}

I am getting following error when I try to map the TimeTableModel to TimeTableEntity:

  1. 'flatMap(maxPublishers:_:)' produces 'Publishers.FlatMap<[TimeTableEntity]?, AnyPublisher<TimetableModel, any Error>>', not the expected contextual result type 'AnyPublisher<[TimeTableEntity]?, any Error>' (Combine.Publisher)

toDomain function:

extension TimetableModel {
    func toDomain() -> [TimeTableEntity]? {
        timetable.departures.map{ TimeTableEntity(lineDirection: $0.lineDirection ?? "", ThroughStations: $0.throughTheStations ?? "", timestamp: $0.datetime.timestamp, timezone: $0.datetime.tz) }
    }
}

Solution

  • It's actually map here and after map, the publisher becomes Publisher.Map<AnyPublisher<[TimeTableEntity]?, Error>>. You have to erase before returning. It should be:

    func getTimeTable() -> AnyPublisher<[TimeTableEntity]?, Error> {
        timeTableRemoteDataSource.getTimeTable()
            .map { $0.toDomain() }
            .eraseToAnyPublisher()
    }
    

    BTW: I think you should also change the optional array to array, to avoid unexpected cases. Just an empty or non-empty array, instead of both empty or non-empty and non-optional and optional.