Swift 合并转换发布者类型
Swift combine Convert Publisher type
我正在探索 Combine Swift 与这个项目 https://github.com/sgl0v/TMDB
我正在尝试用支持 Combine 的东西替换它的 imageLoader:https://github.com/JanGorman/MapleBacon
该项目具有 returns 类型 AnyPublisher<UIImage?, Never>
的功能。
但是 imageLoader MapleBacon 库 returns 类型 AnyPublisher<UIImage, Error>
.
所以我正在尝试使用此函数转换类型:
func convert(_ loader: AnyPublisher<UIImage, Error>) -> AnyPublisher<UIImage?, Never> {
// here.
}
我实际上发现了一个与我的有点相似的问题,但答案没有帮助:
到目前为止我已经尝试过什么(Matt 对相关问题的回答)。
示例项目有这个功能:
func loadImage(for movie: Movie, size: ImageSize) -> AnyPublisher<UIImage?, Never> {
return Deferred { return Just(movie.poster) }
.flatMap({ poster -> AnyPublisher<UIImage?, Never> in
guard let poster = movie.poster else { return .just(nil) }
let url = size.url.appendingPathComponent(poster)
let a = MapleBacon.shared.image(with: url)
.replaceError(with: UIImage(named: "")!) // <----
})
.subscribe(on: Scheduler.backgroundWorkScheduler)
.receive(on: Scheduler.mainScheduler)
.share()
.eraseToAnyPublisher()
}
如果我这样做 replaceError
,
我得到类型 Publishers.ReplaceError<AnyPublisher<UIImage, Error>>
但是,我能够通过扩展库来解决这个问题。
extension MapleBacon {
public func image(with url: URL, imageTransformer: ImageTransforming? = nil) -> AnyPublisher<UIImage?, Never> {
Future { resolve in
self.image(with: url, imageTransformer: imageTransformer) { result in
switch result {
case .success(let image):
resolve(.success(image))
case .failure:
resolve(.success(UIImage(named: "")))
}
}
}
.eraseToAnyPublisher()
}
}
首先,你需要map
一个UIImage
到一个UIImage?
。明智的做法当然是将每个元素包装在一个可选的。
然后,您尝试将有时会产生错误的发布者转变为 Never
会产生错误的发布者。你 replaceError(with:)
一个你选择的元素。您应该用什么元素替换错误?自然的答案是 nil
,因为您的发布商现在发布了 可选 张图片!当然,assertNoFailure
在句法上也是可行的,但是你可能在这里下载图片,所以很可能会发生错误...
最后,我们需要通过 eraseToAnyPublisher
将其变成 AnyPublisher
MapleBacon.shared.image(with: url)
.map(Optional.some)
.replaceError(with: nil)
.eraseToAnyPublisher()
我正在探索 Combine Swift 与这个项目 https://github.com/sgl0v/TMDB 我正在尝试用支持 Combine 的东西替换它的 imageLoader:https://github.com/JanGorman/MapleBacon
该项目具有 returns 类型 AnyPublisher<UIImage?, Never>
的功能。
但是 imageLoader MapleBacon 库 returns 类型 AnyPublisher<UIImage, Error>
.
所以我正在尝试使用此函数转换类型:
func convert(_ loader: AnyPublisher<UIImage, Error>) -> AnyPublisher<UIImage?, Never> {
// here.
}
我实际上发现了一个与我的有点相似的问题,但答案没有帮助:
到目前为止我已经尝试过什么(Matt 对相关问题的回答)。
示例项目有这个功能:
func loadImage(for movie: Movie, size: ImageSize) -> AnyPublisher<UIImage?, Never> {
return Deferred { return Just(movie.poster) }
.flatMap({ poster -> AnyPublisher<UIImage?, Never> in
guard let poster = movie.poster else { return .just(nil) }
let url = size.url.appendingPathComponent(poster)
let a = MapleBacon.shared.image(with: url)
.replaceError(with: UIImage(named: "")!) // <----
})
.subscribe(on: Scheduler.backgroundWorkScheduler)
.receive(on: Scheduler.mainScheduler)
.share()
.eraseToAnyPublisher()
}
如果我这样做 replaceError
,
我得到类型 Publishers.ReplaceError<AnyPublisher<UIImage, Error>>
但是,我能够通过扩展库来解决这个问题。
extension MapleBacon {
public func image(with url: URL, imageTransformer: ImageTransforming? = nil) -> AnyPublisher<UIImage?, Never> {
Future { resolve in
self.image(with: url, imageTransformer: imageTransformer) { result in
switch result {
case .success(let image):
resolve(.success(image))
case .failure:
resolve(.success(UIImage(named: "")))
}
}
}
.eraseToAnyPublisher()
}
}
首先,你需要map
一个UIImage
到一个UIImage?
。明智的做法当然是将每个元素包装在一个可选的。
然后,您尝试将有时会产生错误的发布者转变为 Never
会产生错误的发布者。你 replaceError(with:)
一个你选择的元素。您应该用什么元素替换错误?自然的答案是 nil
,因为您的发布商现在发布了 可选 张图片!当然,assertNoFailure
在句法上也是可行的,但是你可能在这里下载图片,所以很可能会发生错误...
最后,我们需要通过 eraseToAnyPublisher
AnyPublisher
MapleBacon.shared.image(with: url)
.map(Optional.some)
.replaceError(with: nil)
.eraseToAnyPublisher()