Swift:扩展组合运算符

Swift: Extending Combine operators

我正在尝试按照 this 文章的思路包装 tryMap 运算符。

extension Publisher where Output == Data {
    func decode<T: Decodable>(as type: T.Type = T.self, using decoder: JSONDecoder = .init()) -> Publishers.Decode<Self, T, JSONDecoder> {
        decode(type: type, decoder: decoder)
    }
}

extension Publisher where Output == URLSession.DataTaskPublisher.Output {
    func processData(_: @escaping (Self.Output) throws -> Data) -> Publishers.TryMap<Self, Data> {
        tryMap { element -> Data in
            guard let httpResponse = element.response as? HTTPURLResponse,
                  httpResponse.statusCode == 200
            else {
                throw URLError(.badServerResponse)
            }
            return element.data
        }
    }
}

在使用它时我遇到了一个编译器错误,我正在努力解决这个问题:

return urlSession
    .dataTaskPublisher(for: request)
    .processData // <- Value of type '(@escaping (URLSession.DataTaskPublisher.Output) throws -> Data) -> Publishers.TryMap<URLSession.DataTaskPublisher, Data>' (aka '(@escaping ((data: Data, response: URLResponse)) throws -> Data) -> Publishers.TryMap<URLSession.DataTaskPublisher, Data>') has no member 'decode'
    .decode(as: InstantResponse.self)
    .eraseToAnyPublisher()

正确的做法是什么? 谢谢!

首先,您没有调用 processData - 您缺少括号,这实际上会执行函数。其次,您的 processData 声明不正确,它不应将闭包作为其输入参数,因为您无论如何都没有使用该闭包。

extension Publisher where Output == URLSession.DataTaskPublisher.Output {
    func processData() -> Publishers.TryMap<Self, Data> {
        tryMap { element -> Data in
            guard let httpResponse = element.response as? HTTPURLResponse,
                  httpResponse.statusCode == 200
            else {
                throw URLError(.badServerResponse)
            }
            return element.data
        }
    }
}

return urlSession
    .dataTaskPublisher(for: request)
    .processData() // parentheses necessary here
    .decode(as: InstantResponse.self)
    .eraseToAnyPublisher()