You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 23:06:06