发布嵌套在字典中的提取数组,并使用Combine和Swift为其返回发布者



我正在使用combine实现一个网络层,并且很难在一次滑动中提取内部数组作为发布者。我有它的工作,但作为两个独立的函数,在第二个函数中。水槽我拉我需要的东西,但我希望这一切都发生在第一个函数中。。。当前状态,以供下文参考。

json从api返回供参考:

{
"count": 1,
"entities": [
{facetids:[],
identifiers:[],
description:String},
{facetids:[],
identifiers:[],
description:String}
]
}

实体的样子:

struct Entities:Decodable
{
var count:Int?
var entities: [Entity]?
}

NetworkController.swift:

func get<T>(type: T.Type, url: URL, headers: Headers) -> AnyPublisher<T, Error> where T : Decodable
{
var urlRequest = URLRequest(url: url)

headers.forEach
{
key, value in

if let value = value as? String
{
urlRequest.setValue(value, forHTTPHeaderField: key)
}
}
return URLSession.shared.dataTaskPublisher(for: urlRequest)
return URLSession.shared.dataTaskPublisher(for: urlRequest)
.map(.data)
.decode(type: T.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}

EntitiesLogicController.swift:

func getEntities(named: String, count: Int) -> AnyPublisher<Entities, Error> {
let endpoint = Endpoint.companies(named: named, count: count)

return networkController.get(type: Entities.self, url: endpoint.url, headers: endpoint.headers)
}

ApiCaller.swift:

func getEntities(named: String)
{
entitiesLogicController?.getEntities(named: named, count: 20).sink{
[weak self] completion in

if case let .failure(error) = completion
{
print("Error retrieving Entity, ERROR: (error)")
} else if case .finished = completion
{
print("Data successfully downloaded")
}
} receiveValue:
{
requestedEntity in

do{
let entities:[Entity] = try requestedEntity.entities!.compactMap{
entity in
do
{
return try Entity(from: entity)
}
}
self.entities = entities
}catch
{
print("Error")
}
}.store(in: &subscriptions)
}

我想要/需要返回AnyPublisher<[T] ,错误>相反其中[T]==[Entity]可解码结构工作得非常好,其他一切也一样。

如果您想要the get to return AnyPublisher<[T], Error> instead where [T] == [Entity],那么您应该有一个通用LogicController,它将处理通用调用,而不是EntitiesLogicController.swift

GenericLogicController.swift

func getObjects<T>(parameters: [String: Any]) -> AnyPublisher<T, Error> where T : Decodable {
let endpoint = //create a genric endpoint - or use switch to differentiate
return networkController.get(type: T.self, url: endpoint.url, headers: endpoint.headers)
} 

最新更新