Swift Combine Add Operator Method,How to Make Return Value Simple and Short,Like Publishers.Flatmap<Xxxpublisher<Xxx>.Xx> to Anypublisher<Xxx, Error>

Is there a way to simplify Swift combine types?

You would just call eraseToAnyPublisher() on the result.

Combine uncollect operator?

You can use flatMap together with a new publisher

[1,2,3,4,5,6].publisher
.collect()
.flatMap { $0.publisher }
.sink { print($0) }

1

2

3

4

5

6

How Can I Flatten An AnyPublisherAnyPublisher?

This line .map { (arg) -> AnyPublisher<[T], LoadingError> in needs to be a flatMap.

Using Just with flatMap produce Failure mismatch. Combine

There is special operator setFailureType(to:). You can override failure type to whatever error type you need.

func request(request: URLRequest) -> AnyPublisher<Data, Error> {
return Just(request)
.setFailureType(to: Error.self)
.flatMap { request in
RequestManager.request(request) // returns AnyPublisher<Data, Error>
}
.eraseToAnyPublisher()
}

https://developer.apple.com/documentation/combine/just/3343941-setfailuretype

Mapping Swift Combine Future to another Future

You can't use dribs and drabs and bits and pieces from the Combine framework like that. You have to make a pipeline — a publisher, some operators, and a subscriber (which you store so that the pipeline will have a chance to run).

 Publisher
|
V
Operator
|
V
Operator
|
V
Subscriber (and store it)

So, here, getItem is a function that produces your Publisher, a Future. So you can say

getItem (...)
.map {...}
( maybe other operators )
.sink {...} (or .assign(...))
.store (...)

Now the future (and the whole pipeline) will run asynchronously and the result will pop out the end of the pipeline and you can do something with it.

Now, of course you can put the Future and the Map together and then stop, vending them so someone else can attach other operators and a subscriber to them. You have now assembled the start of a pipeline and no more. But then its type is not going to be Future; it will be an AnyPublisher<NSImage,Error>. And there's nothing wrong with that!

Swift Combine transform an array of publishers

The general approach is to flatMap the array into a Sequence publisher of individual values, then do any async operations on each value (another flatMap), then collect the results:

HKHealthStore()
.workouts(HKObjectQueryNoLimit)
.flatMap { workouts in workouts.publisher }
.flatMap { workout in
workoutDetails(workout)
}
.collect()
.sink(
receiveCompletion: { ... },
receiveValue: { arrayOfWorkoutDetails in
// arrayOfWorkoutDetails is of type [WorkoutDetails]
})
.store(in: &bag)

Using flatMap in RestManager with generic function not working

There are several major flows in your implementation.

Firstly, you shouldn't be using Result as the Output type of the Publisher and Never as its Failure type. You should be using T as the Output and ErrorType as Failure.

Second, you need tryMap and mapError, not flatMap.

Lastly, you are handling the result of dataTaskPublisher completely wrong. When dataTaskPublisher fails, it emits an error, so you need to handle that in mapError. When it succeeds, it emits its result as data, so you need to be decoding that, not response.

func fetchData<T: Decodable>(url: URL) -> AnyPublisher<T, ErrorType> {
URLSession
.shared
.dataTaskPublisher(for: url)
.tryMap { data, _ in
return try JSONDecoder().decode(T.self, from: data)
}
.mapError { error -> ErrorType in
switch error {
case let urlError as URLError:
switch urlError.code {
case .notConnectedToInternet, .networkConnectionLost, .timedOut:
return .noInternetConnection
case .cannotDecodeRawData, .cannotDecodeContentData:
return .empty
default:
return .general
}
default:
return .general
}
}
.eraseToAnyPublisher()
}


Related Topics



Leave a reply



Submit