在Combine中将一个发布者转换为另一个发布器



我是新组合的,我正在尝试为我的应用程序编写网络层。

我的网络呼叫是

protocol NetworkRequest {
associatedtype model
func decode(_ data:Data) -> AnyPublisher<model,Error>
}
extension NetworkRequest {
fileprivate func load<model>(_ url:URL, session:NetworkSession = URLSession.shared) -> AnyPublisher<model,Error> {

return session.loadData(for: URLRequest(url: url))
.mapError { error in
.network(description: error.localizedDescription)
}
.flatMap(maxPublishers: .max(1)) { pair in
self.decode(pair.data)
}
.eraseToAnyPublisher()

}
}

我的解码方法是

func decode(_ data:Data) -> AnyPublisher<model,Error>

和我的会话。loadData是

func loadData(for URLRequest: URLRequest) -> AnyPublisher<(data: Data, response: URLResponse), URLError>

问题是我收到一个错误Type of expression is ambiguous without more context

我不太清楚我在这里做错了什么。我只是想使用解码方法来获得一个发布者。

这里的类型不匹配。publisher的类型是AnyPublisher,而您分配给它的类型是一个FlatMap。这种情况通常发生在使用运算符时,解决方案是使用.eraseToAnyPublisher()运算符键入擦除:

var publisher : AnyPublisher<Model, Error> = 
session.loadData(for: URLRequest(url: url))
.flatMap { (data,response) -> AnyPublisher<Model,Error> in
self.decode(data)
}
.eraseToAnyPublisher() // add this

Btw,您应该对类型使用CapitalBase,例如Model


更新:根据您的问题更改

这又是一个类型不匹配,但在本例中,是Model类型。当您这样声明load函数时:

func load<Model>(_ url: URL, ...) -> AnyPublisher<Model,Error> {

函数的泛型类型Model与关联类型Model不同——它们是完全不同的类型,只是具有相同的名称。因此,decode返回Self.Model,但load希望返回自己的Model,因此存在不匹配。

解决方案是简单地从签名中删除函数的Model

func load(_ url: URL, ...) -> AnyPublisher<Model, Error>

Combine大量使用类型推理,当它工作时会大大简化事情,或者当它不工作时会给出神秘和错误的错误。要使用Combine诊断类似的错误,请使用显式类型。例如,在flatMap中明确指定要返回的类型:

.flatMap(maxPublishers: .max(1)) { pair -> AnyPublisher<Model, Error> in
self.decode(pair.data)
}

上面的人会抱怨CCD_ 17和CCD_。

最新更新