Combine中`compactMap { $0 }`的简写:能否通过扩展实现`compactMap()`?
实现无闭包的
compactMap()语法糖移除Publisher中的nil值 当然可以实现这种语法糖,直接给Combine的Publisher扩展一个无参的compactMap()方法,专门处理输出为可选类型的流,自动过滤nil并解包非可选值。
实现代码
import Combine // 定义协议统一处理可选类型 protocol OptionalType { associatedtype Wrapped var wrappedValue: Wrapped? { get } } // 让所有Optional类型遵循该协议 extension Optional: OptionalType { var wrappedValue: Wrapped? { self } } // 给Publisher扩展无参compactMap extension Publisher where Output: OptionalType { func compactMap() -> Publishers.CompactMap<Self, Output.Wrapped> { compactMap { $0.wrappedValue } } }
使用示例
假设你有一个输出可选类型的Publisher:
var cancellables = Set<AnyCancellable>() let optionalNumberPublisher = PassthroughSubject<Int?, Never>() // 原来的写法 optionalNumberPublisher .compactMap { $0 } .sink(receiveValue: { print("原写法输出:\($0)") }) .store(in: &cancellables) // 现在的语法糖写法 optionalNumberPublisher .compactMap() .sink(receiveValue: { print("语法糖写法输出:\($0)") }) .store(in: &cancellables) // 发送测试值 optionalNumberPublisher.send(1) optionalNumberPublisher.send(nil) optionalNumberPublisher.send(2)
说明
- 这个扩展仅对输出为可选类型的
Publisher生效,如果你的Publisher输出不是可选值,调用compactMap()会直接编译报错,避免误用。 - 内部其实还是调用了系统的
compactMap方法,只是帮你省略了重复写{ $0 }的步骤,完全符合你想要的简化效果。
内容的提问来源于stack exchange,提问作者Trev14
相关产品推荐
相关产品推荐

