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

时间:2020-03-02 11:08:44

标签: ios swift combine

我有这两个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并将其解码为Parent对象:

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()
}

它可以工作,但是我想要一种方法来检索子级数组,而不是像这样的Parent对象:

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

但是我不知道我需要改变什么。任何帮助,我们都会感激的,谢谢!

1 个答案:

答案 0 :(得分:4)

您只需要调用parent函数并在其map上调用Publisher即可恢复其children属性。

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

与您的问题无关,但我建议您摆脱您的Result类型。首先,它与Swift的内置Result类型冲突。其次,在成功的网络请求的情况下存储URLResponse,返回有效数据并不会真正增加任何值。 URLResponse主要在失败或请求未返回值的情况下保留值,而是成功响应代码(200、206等)。

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

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