Combine中merge操作符输出如何正确使用eraseToAnyPublisher?
问题:如何让Combine的merge输出完全擦除为指定的AnyPublisher类型?
问题重现
初始代码如下:
let a = PassthroughSubject<Int, Never>() let b = PassthroughSubject<Int, Never>() let result = a.merge(with:b).eraseToAnyPublisher()
原本预期result的类型为AnyPublisher<Int, Never>,但Xcode显示的类型为(格式化空白后):
AnyPublisher< Publishers.MergeMany< PassthroughSubject<Int, Never> >.Output, Publishers.MergeMany< PassthroughSubject<Int, Never> >.Failure > (aka 'AnyPublisher<Int, Never>')
尝试提前对单个Subject做类型擦除:
let a = PassthroughSubject<Int, Never>().eraseToAnyPublisher() let b = PassthroughSubject<Int, Never>().eraseToAnyPublisher() let result = a.merge(with:b).eraseToAnyPublisher()
Xcode显示的类型仅略有变化:
AnyPublisher< Publishers.MergeMany< AnyPublisher<Int, Never> >.Output, Publishers.MergeMany< AnyPublisher<Int, Never> >.Failure > (aka 'AnyPublisher<Int, Never>')
核心疑问:如何让merge操作的输出通过eraseToAnyPublisher()完全擦除为预期的AnyPublisher<Int, Never>类型,让Xcode直接显示该简化类型?
解决方法
这是Xcode的类型显示特性——它会保留泛型的原始关联类型路径,但实际上result的实际运行类型就是AnyPublisher<Int, Never>(从标注的aka可以确认)。要让Xcode直接显示简化后的类型,有两种可行方式:
1. 显式指定变量类型
直接给result标注预期的类型,Xcode就会显示你指定的简化类型:
let a = PassthroughSubject<Int, Never>() let b = PassthroughSubject<Int, Never>() let result: AnyPublisher<Int, Never> = a.merge(with: b).eraseToAnyPublisher()
2. 使用类型别名封装
如果需要重复使用该类型,可以定义类型别名来简化代码和显示:
typealias IntNeverPublisher = AnyPublisher<Int, Never> let a = PassthroughSubject<Int, Never>().eraseToAnyPublisher() let b = PassthroughSubject<Int, Never>().eraseToAnyPublisher() let result: IntNeverPublisher = a.merge(with: b).eraseToAnyPublisher()
补充说明
eraseToAnyPublisher()已经完成了类型擦除工作,Xcode显示的复杂类型只是它对泛型关联类型的展开展示,不会影响代码的运行逻辑和类型安全。- 显式指定类型还能在编译阶段就确保类型符合预期,避免潜在的类型不匹配问题。
内容的提问来源于stack exchange,提问作者Curious Jorge
相关产品推荐
相关产品推荐

