简体   繁体   中英

Swift combine get custom objects from AnyPublisher

I'm trying to fetch 'Post' objects from the API with AnyPublisher, but I'm unable to get the result. How can we achieve result from AnyPublisher<[Post], Error>

Here is my code,


import UIKit
import Combine

struct Post: Decodable{
    var id: Int
    var userId: Int
    var body: String
    var title: String

}

protocol API {
    var baseUrl: String { get }
    var path: URL { get }
}

enum PostService: API {

    var baseUrl : String { "https://jsonplaceholder.typicode.com" }
    case all
    var path: URL {
        switch self {
        case .all:
            return URL(string: baseUrl + "/posts")!
        }
    }

    func fetch(from url: URL) -> AnyPublisher<[Post], Error> {
        return URLSession.shared
            .dataTaskPublisher(for: url)
            .mapError { $0 as Error }
            .map(\.data)
            .decode(type: [Post].self, decoder: JSONDecoder())
            .eraseToAnyPublisher()

    }
}

PostService.fetch(.all)  
// how to get all posts here

Your code is wrong, at least the way you are calling it, I assume it should be something like this


enum PostService: API {

    var baseUrl : String { "https://jsonplaceholder.typicode.com" }
    case all
    var path: URL {
        switch self {
        case .all:
            return URL(string: baseUrl + "/posts")!
        }
    }

    func fetch() -> AnyPublisher<[Post], Error> {
        return URLSession.shared
            .dataTaskPublisher(for: path)
            .mapError { $0 as Error }
            .map(\.data)
            .decode(type: [Post].self, decoder: JSONDecoder())
            .eraseToAnyPublisher()

    }
}

then you would be able to subscribe to it like so


PostService.all.fetch().sink { completion in

} receiveValue: { posts in

}

If you really want to keep call syntax the way you wrote it, you would need to update your code like this


enum PostService: API {

    var baseUrl : String { "https://jsonplaceholder.typicode.com" }
    case all
    var path: URL {
        switch self {
        case .all:
            return URL(string: baseUrl + "/posts")!
        }
    }

    static func fetch(from url: Self) -> AnyPublisher<[Post], Error> {
        return URLSession.shared
            .dataTaskPublisher(for: url.path)
            .mapError { $0 as Error }
            .map(\.data)
            .decode(type: [Post].self, decoder: JSONDecoder())
            .eraseToAnyPublisher()

    }
}

note the fetch method is static now

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM