0

Given an existing CurrentValueSubject instance, the goal is to create a new Publisher that will take the subject's stream of Strings, and in turn will output Ints.

My approach is to map the subject to AnyPublisher:

let subject: CurrentValueSubject<String, Never> = ...

func intPublisher() -> AnyPublisher<Int, Never>
{
    return subject.map { string in
        let value = Int(string) ?? 0
        return AnyPublisher<Int, Never>(value) // Error: Generic parameter P could not be inferred.
    }
}

However, I cannot create a new AnyPublisher this way. Clearly, my understanding of Publishers is flawed. Could someone please enlighten me?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Womble
  • 4,607
  • 2
  • 31
  • 45

1 Answers1

4

You're just a bit off.

.map maps values, so you need to return a new value, not a new publisher. Then use .eraseToAnyPublisher to create the AnyPublisher publisher:

func intPublisher() -> AnyPublisher<Int, Never> {
   subject.map { Int($0) ?? 0 }
          .eraseToAnyPublisher()
}

You can also use AnyPublisher(subject.map { Int($0) ?? 0 }) as well (the init parameter is a publisher, not a value).


For completeness, you can return a publisher for each value, but then you'd need to use a flatMap. The following achieves the same result as above, but just in an unnecessarily convoluted way:

subject.flatMap { string in
      Just( Int(string) ?? 0 )
   }.eraseToAnyPublisher()

New Dev
  • 48,427
  • 12
  • 87
  • 129
  • Thank you! That's exactly what I needed. Much appreciated. – Womble Aug 01 '20 at 06:35
  • The part about flatMap helped me a lot! Thank you. I tried to combine (zip) a second publisher per value of the main publisher to make a second network call and pass the received data to the model I received with the first network call. – the.blaggy Jan 19 '21 at 12:41