Kamilpro
Kamilpro

Reputation: 55

Result with combine can't get results

I kind of wrote everything correctly and the code itself is working but it gives me an error Result of call to 'fetchPokemon()' is unused, what could be the problem here?

Hear is my code: ModelView class

 import Foundation
 import Combine
 class NetworkManager: ObservableObject {

let baseuRL = "https://pokeapi.co/api/v2/pokemon"

@Published var pokemon: [Pokemon] = []
var error: Error?
var cancellables: Set<AnyCancellable> = []

func fetchPokemon() -> Future<[Pokemon], Error> {
    return Future<[Pokemon], Error> { promice in
        guard let url = URL(string: "\(self.baseuRL)") else {
            return promice(.failure(ApiError.unknowed))
        }
        URLSession.shared.dataTaskPublisher(for: url)
            .tryMap { (data, response) -> Data in
                guard let http = response as? HTTPURLResponse,
                      http.statusCode == 200 else {
                    throw ApiError.responseError
                }
                return data
            }
            .decode(type: PokemonList.self, decoder: JSONDecoder())
            .receive(on: RunLoop.main)
            .sink(receiveCompletion: { completion in
                switch completion {
                case .finished:
                    break
                case .failure(let error):
                    print(error)
                }
            }, receiveValue: {
                promice(.success($0.results))
            })
            .store(in: &self.cancellables)
    }
}


 struct ContentView: View {
@StateObject var net = NetworkManager()
var body: some View {
    List(net.pokemon, id: \.self) { pokemon in
        Text(pokemon.name)
    }.onAppear {
        net.fetchPokemon()
    }
}

}

Upvotes: 0

Views: 386

Answers (1)

jnpdx
jnpdx

Reputation: 52347

Your fetchPokemon function returns a Future, but you're not doing anything with it -- that's why you're getting the unused error.

Also, in that function, you're returning your promise, but not doing anything with the results. So, you need to handle the Future and do something with those results.

It might look something like the following:


class NetworkManager: ObservableObject {
    
    let baseuRL = "https://pokeapi.co/api/v2/pokemon"
    
    @Published var pokemon: [Pokemon] = []
    var error: Error?
    var cancellables: Set<AnyCancellable> = []
    
    //New function here:
    func runFetch() {
        fetchPokemon().sink { (completion) in
            //handle completion, error
        } receiveValue: { (pokemon) in
            self.pokemon = pokemon //do something with the results from your promise
        }.store(in: &cancellables)
    }
    
    private func fetchPokemon() -> Future<[Pokemon], Error> {
        return Future<[Pokemon], Error> { promice in
            guard let url = URL(string: "\(self.baseuRL)") else {
                return promice(.failure(ApiError.unknowed))
            }
            URLSession.shared.dataTaskPublisher(for: url)
                .tryMap { (data, response) -> Data in
                    guard let http = response as? HTTPURLResponse,
                          http.statusCode == 200 else {
                        throw ApiError.responseError
                    }
                    return data
                }
                .decode(type: PokemonList.self, decoder: JSONDecoder())
                .receive(on: RunLoop.main)
                .sink(receiveCompletion: { completion in
                    switch completion {
                    case .finished:
                        break
                    case .failure(let error):
                        print(error)
                    }
                }, receiveValue: {
                    promice(.success($0.results))
                })
                .store(in: &self.cancellables)
        }
    }
}


struct ContentView: View {
    @StateObject var net = NetworkManager()
    var body: some View {
        List(net.pokemon, id: \.self) { pokemon in
            Text(pokemon.name)
        }.onAppear {
            net.runFetch() //call runFetch instead of fetchPokemon
        }
    }
}

Since you didn't include the code for PokemonList I made an assumption about it's content:

struct PokemonList: Codable {
    var results: [Pokemon]
}

If the type is different, you'll have to change what happens in receiveValue in runFetch.

Upvotes: 2

Related Questions