iOS - 合并 - 将发布商类型更改为子类型

iOS - Combine - Change Publisher type to child type

我有这两个 Codable 对象:

struct Parent: Codable {
    let name: String
    let children: [Child]
}

struct Child: Codable {
    let name: String
} 

我创建来匹配这个 json :

{
    name: "test"
    children: (
        {
          name: "test2"
        },
        {
          name: "test3"
        }
     )
}

我检索 json 并使用这些方法将其解码为父对象:

func parent(_ url: String) -> AnyPublisher<Parent, Error> { 
    return dataFromURL(url)
        .map(\.value)
        .eraseToAnyPublisher()
}

struct Result<T> {
    let value: T
    let response: URLResponse
}

func dataFromURL<T: Decodable>(_ url: String, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Result<T>, Error> {
    let request = URLRequest(url: URL(string:url)!)
    return URLSession.shared
        .dataTaskPublisher(for: request)
        .tryMap { result -> Result<T> in
            let value = try decoder.decode(T.self, from: result.data)
            return Result(value: value, response: result.response)
        }
        .receive(on: DispatchQueue.main)
        .eraseToAnyPublisher()
}

它有效,但我想要一种方法来检索子数组,而不是父对象,如下所示:

func children(_ url: String) -> AnyPublisher<[Child], Error>  

但我不知道我需要更改什么.. 任何帮助将不胜感激,谢谢!

您只需调用 parent 函数并在其 Publisher 上调用 map 即可取回其 children 属性.

func children(from url: String) -> AnyPublisher<[Child], Error> {
    return parent(url)
        .map(\.children)
        .eraseToAnyPublisher()
}

与您的问题无关,但我建议摆脱您的 Result 类型。首先,它与Swift的内置Result类型冲突。其次,存储 URLResponse 以防网络请求成功,returned 有效数据并没有真正增加任何价值。 URLResponse 主要在失败或请求没有 return 值但成功响应代码(200、206 等)时保留值。

更新:如果您想摆脱 parent(_:) 方法,只需将 map(\.children) 调用链接到原始 parent(_:) 方法的内容即可。为了让编译器推断 dataFromURL(_:) 方法的泛型 return 类型,您只需在第二个 map 调用中将 KeyPath 指定为 \Parent.children .

func children(from url: String) -> AnyPublisher<[Child], Error> {
    return dataFromURL(url)
        .map(\.value)
        .map(\Parent.children)
        .eraseToAnyPublisher()
}