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

在Combine中如何映射为Encodable类型解决Publisher类型转换报错

问题原因

你协议中output指定的返回类型是Published<Encodable>.Publisher这一具体发布者类型,但你对handler.$userTextOutput做map转换后得到的是Publishers.Map<Published<String>.Publisher, Encodable>类型,二者不属于同一具体类型,因此触发类型不匹配报错。

解决方案
  1. 首先修改协议定义,不要限定output为具体的Published发布者类型,改用类型抹除后的AnyPublisher<Encodable, Never>,适配不同输入字段的发布者转换场景。
  2. 补充实现类型擦除的AnyEncodable结构体,避免直接返回Encodable协议类型时无法正常编码的问题(Encodable作为类型本身不遵循Encodable协议,直接使用会触发编码错误)。
  3. 对map转换后的发布者调用eraseToAnyPublisher()完成类型抹除,匹配协议定义的返回类型。
完整修改后代码
import Combine

// 类型擦除的Encodable包装,解决协议类型无法直接编码的问题
struct AnyEncodable: Encodable {
    private let value: Encodable
    
    init(_ value: Encodable) {
        self.value = value
    }
    
    func encode(to encoder: Encoder) throws {
        try value.encode(to: encoder)
    }
}

protocol FieldResponseModifying {
    var id: String { get }
    // 改用类型抹除的发布者,不限制具体发布者类型
    var output: AnyPublisher<AnyEncodable, Never> { get }
}

struct SampleTextWrapper: FieldResponseModifying {
    var output: AnyPublisher<AnyEncodable, Never> {
        handler.$userTextOutput
            .map { AnyEncodable($0) }
            .eraseToAnyPublisher()
    }
    
    let id = UUID().uuidString
    let handler = SampleTextHandler()
}

class SampleTextHandler {
   @Published var userTextOutput = ""
    init () { }
}
扩展说明

如果你的输入字段支持日期、数字等其他类型,只需要在对应Wrapper的map转换中把值包装成AnyEncodable即可,所有字段的输出都可以统一为AnyPublisher<AnyEncodable, Never>类型,方便后续合并所有输入流、统一编码上传。

内容的提问来源于stack exchange,提问作者Dr. Mr. Uncle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 20:54:04