iosswiftswiftui

API calls for SwiftUI application


I'm trying to make an easy application in SwiftUI for iOS. I'm following the instructions of a YouTube video which shows how to make an API call from PokeAPI in order to show a List of Pokemon in the view. I made every single step equal to those of the video but the compiler returns me errors like these in the code below.

PokemonAPIList.swift

import Foundation

struct PokemonAPIList: Decodable {
    var results: [PokemonListEntry]
}

struct PokemonListEntry: Decodable {
    var name: String
    var url: String
}

PokemonNetworkManager.swift

import Foundation
import SwiftUI
import Combine

class PokemonNetworkManager: ObservableObject {
    var didChange = PassthroughSubject<PokemonNetworkManager, Never> ()
    
    var pokemonList = PokemonAPIList(results: []) {
        didSet {
            didChange.send(self)
        }
    }
    
    init() {
        guard let url = URL(string: "https://pokeapi.co/api/v2/pokemon?limit=151") else { return }
        
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            guard let data = data else { return }
            
            let pokemonList = try! JSONDecoder().decode(PokemonAPIList.self, from: data)
            
            DispatchQueue.main.async {
                self.pokemonList = pokemonList
            }
        }.resume()
    }
}

ContentView.swift

import SwiftUI
    
struct ContentView: View {
    @State var networkingManager = PokemonNetworkManager()
    
    var body: some View {
        List(networkingManager.pokemonList.results.identified(by: \.url)) {pokemon in //HERE THE ERRORS
            Text(pokemon.name)
                .font(.largeTitle)
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

Following Errors occur:

Cannot infer key path type from context; consider explicitly specifying a root type
Insert '<#Root#>'
Value of type '[PokemonListEntry]' has no member 'identified'

The only thing I changed is @BindableObject to @ObservableObject because I read online it is no longer supported.


Solution

  • You can try

    import Foundation
    import SwiftUI
    import Combine
     
    struct PokemonAPIList: Decodable {
        var results: [PokemonListEntry]
    }
    
    struct PokemonListEntry: Decodable {
        var name: String
        var url: String
    }
     
    class PokemonNetworkManager: ObservableObject {
      
       @Published var results = [PokemonListEntry]()
         
        init() {
            guard let url = URL(string: "https://pokeapi.co/api/v2/pokemon?limit=151") else { return }
            
            URLSession.shared.dataTask(with: url) { (data, _, _) in
                guard let data = data else { return }
                
                let pokemonList = try! JSONDecoder().decode(PokemonAPIList.self, from: data)
                
                DispatchQueue.main.async {
                    self.results = pokemonList.results
                }
            }.resume()
        }
    }
      
    struct ContentView: View {
        @ObservedObject var networkingManager = PokemonNetworkManager()
        
        var body: some View {
            List(networkingManager.results,id:\.name) {pokemon in
                Text(pokemon.name)
                    .font(.largeTitle)
            }
        }
    }
     
    

    enter image description here