Combine中如何使用可选结构体变量实现SCEvent转EventModel?
实现方案说明
你的需求完全可以通过单个Publisher链实现,不需要依赖外部分支判断,同时也不需要发起无效空路径请求。
首先你理想写法的核心问题是:event.imagePath是Swift可选值类型,不是Combine Publisher类型,无法直接调用Combine的操作符,只需要先把它包装为Publisher即可。
最优单链实现
func loadEvent(_ event: SCEvent) -> AnyPublisher<EventModel, Error> { // 把可选imagePath包装为Publisher Just(event.imagePath) // 对齐错误类型:Just默认错误类型为Never,需要和下载接口的错误类型统一 .setFailureType(to: Error.self) .flatMap { imagePath -> AnyPublisher<Data, Error> in // 内部处理可选分支,nil直接返回空Data,不会发起无效请求 guard let path = imagePath else { return Just(Data()) .setFailureType(to: Error.self) .eraseToAnyPublisher() } // 非nil走正常下载逻辑 return DataDownloader.downloadData(fromPath: path) .eraseToAnyPublisher() } .map { data in EventModel(name: event.name, imageData: data) } .eraseToAnyPublisher() }
补充说明
- 你的初始分支写法其实没有问题,可读性反而比单链写法更高,逻辑边界清晰,不需要为了强行写单链而牺牲可读性。
- 你提到的空字符串替换+错误捕获的方案确实不推荐,会发起完全不必要的无效下载请求,凭空增加性能损耗。
- 如果需要最终
EventModel数组的顺序和输入SCEvent数组的顺序完全一致,可以把loadEvents里的flatMap改为flatMap(maxPublishers: .max(1)),限制并发数为1避免乱序。
内容的提问来源于stack exchange,提问作者Carles Mitjans
相关产品推荐
相关产品推荐

