Search code examples
combineios14

Issue with Combine when migrating to iOS 14


I have an issue when migrating from iOS 13 to iOS 14. The following code was compiling fine before:

func fetchOptions(
    forLatitude latitude: Double,
    andLongitude longitude: Double,
    ofTypes types: [Option.Type],
    completion: @escaping (Result<[Option], Error>) -> Void
  ) {
    var cancellables: Set<AnyCancellable> = []

    Deferred {
        Future { handler in
            self.someFetcher.fetchServices(
                byLatitude: latitude,
                andLongitude: longitude,
                completion: handler
            )
        }
      }.eraseToAnyPublisher()
      .flatMap { Publishers.Sequence(sequence: $0).eraseToAnyPublisher() }
      .filter { types.map { $0.id}.contains($0.id) }
      .flatMap {
        Publishers.Zip(
          Just($0).setFailureType(to: Error.self),
          Deferred {
            Future { handler in
              self.fetcher.fetch(forId: id, completion: handler)
            }
          }.eraseToAnyPublisher()
        ).eraseToAnyPublisher()
      }
      .compactMap(mapToOption)
      .collect()
      .map { Array(Set($0)) }
      .sink { complete in
        switch complete {
        case .failure(let error): completion(.failure(error))
        case .finished: return
        }
        cancellables.forEach { $0.cancel() }
      } receiveValue: { options in
        completion(.success(options))
      }
      .store(in: &cancellables)
  }

But now I am getting the error: "Ambiguous use of 'flatMap(maxPublishers:_:)' Found this candidate (Combine.Publisher) Found this candidate (Combine.Publisher)"

How can I solve this ? I only have little experience using Combine.


Solution

  • Finally, I got it working by asking ChatGPT.

    "The error you are encountering is due to an ambiguous use of the flatMap operator in the Combine framework, which occurred after migrating to iOS 14. In iOS 14, the flatMap operator has multiple overloads, which are causing the ambiguity. To resolve this issue, you can explicitly specify the type of the flatMap operator using the publishers namespace. This way, you can choose the appropriate overload of the flatMap operator that matches your code's requirements. Here's the modified code with the explicit use of the publishers namespace:

    // ... .flatMap { (services: [Service]) -> AnyPublisher<Service, Error> in // Explicitly specify the type // ... "

    I simply updated the two flatMap operators:

    • .flatMap { (services: [Service]) -> AnyPublisher<Service, Error> in
    • .flatMap { (service: DeliveryService) -> AnyPublisher<(DeliveryService, Double), Error> in