Swift Combine管道转换带图片Car对象报错及功能实现问题
解决方案
核心修改说明
- 修复flatMap类型歧义:统一if/else分支的返回Publisher类型,消除编译器类型推导错误
- 移除
compactMap避免丢失无图片条目:图片拉取失败/无图片链接时直接返回image为nil的CarWithImage对象,不做过滤 - 新增延迟模拟:车辆列表返回前加4秒延迟模拟接口请求,图片拉取前加6秒延迟模拟网络下载
- 错误兼容:图片拉取产生的错误全部替换为nil,不会终止整个管道,保证所有车辆条目都正常返回
完整可运行代码
import UIKit import Combine import PlaygroundSupport // 保证Playground延迟执行时不会提前终止 PlaygroundPage.current.needsIndefiniteExecution = true struct Car { let name: String let imageString: String? } struct CarWithImage { let name: String let image: UIImage? } final class CarClass { let myCars = [Car(name: "Tesla", imageString: "car"), Car(name: "Volvo", imageString: nil)] let delayCar: TimeInterval = 4 let delayImage: TimeInterval = 6 func getVehicles() -> AnyPublisher<[CarWithImage], Error> { myCars.publisher // 模拟车辆列表接口请求延迟 .delay(for: .seconds(delayCar), scheduler: DispatchQueue.main) .setFailureType(to: Error.self) .flatMap { [weak self] car -> AnyPublisher<CarWithImage, Error> in guard let self = self else { return Just(CarWithImage(name: car.name, image: nil)) .setFailureType(to: Error.self) .eraseToAnyPublisher() } // 有图片链接则走拉取逻辑,无则直接返回image为nil的对象 if let imageString = car.imageString { return self.getImage(imageString) // 图片拉取错误时替换为nil .replaceError(with: nil) .map { CarWithImage(name: car.name, image: $0) } .setFailureType(to: Error.self) .eraseToAnyPublisher() } else { return Just(CarWithImage(name: car.name, image: nil)) .setFailureType(to: Error.self) .eraseToAnyPublisher() } } .collect() .eraseToAnyPublisher() } func getImage(_ string: String) -> AnyPublisher<UIImage?, Error> { Just(UIImage(systemName: string)) // 模拟图片下载延迟 .delay(for: .seconds(delayImage), scheduler: DispatchQueue.main) .setFailureType(to: Error.self) .eraseToAnyPublisher() } } // 测试代码 let carClass = CarClass() carClass.getVehicles() .sink(receiveCompletion: { print($0)}) { cars in cars.forEach { car in let haveImage = car.image != nil let string = haveImage ? "and it have an image" : "" print("The car is", car.name, string) } // 执行完成后停止Playground无限执行 PlaygroundPage.current.finishExecution() }
运行效果
等待10秒(4秒车辆延迟+6秒图片延迟)后会输出:
The car is Tesla and it have an image The car is Volvo finished
内容的提问来源于stack exchange,提问作者Ivan C Myrvold
相关产品推荐
相关产品推荐

