UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: API Call Help

Forums > iOS

Hi all,

Longtime listener, first time caller. Finally able to sit down with URLSession.shared.dataTaskPublisher and play around.

Not sure why but I can't get a response from APIs like SpaceX or RickandMorty. Threw various links that worked into Postman and I noticed the ones that don't work open the reponse with '{' where Paul's url user-messages.json opens the reponse with '['

Below is an example of my attempt with the SpaceX API - Latest Launches. Any advise would be great because clearly I'm missing something fundamental.

import SwiftUI
import Combine

struct SpaceX: Codable {
    var flight_number: Int
    var name: String
}

struct ContentView: View {
    @State private var requests = Set<AnyCancellable>()
    @State private var launchesLatest = [SpaceX]()

    var body: some View {
        NavigationView {
            List(launchesLatest, id: \.name) { launches in
                Text(launches.name)
            }
        .navigationBarTitle("SpaceX")
        }
        .onAppear {
            let url = URL(string: "https://api.spacexdata.com/v4/launches/latest")!

            self.fetch(url, defaultValue: [SpaceX]()) {
                self.launchesLatest = $0
            }
        }
    }

    func fetch<T: Decodable>(_ url: URL, defaultValue: T, completion: @escaping (T) -> Void) {

        let decoder = JSONDecoder()

        URLSession.shared.dataTaskPublisher(for: url)
            .retry(1)
            .map(\.data)
            .decode(type: T.self, decoder: decoder)
            .replaceError(with: defaultValue)
            .receive(on: DispatchQueue.main)
            .sink(receiveValue: completion)
            .store(in: &requests)
    }
}

3      

Hi @teamsuperpanda,

It because the JSON is not an Array [ ] there forewill only return one value. Add to your struct SpaceX

struct SpaceX: Decodable {
  var flight_number: Int
  var name: String

  static let `default` = SpaceX(flight_number: 0, name: "Unknown")
}

then change the ContentView

@State private var requests = Set<AnyCancellable>()
@State var spaceX: SpaceX

var body: some View {
  NavigationView {
      VStack {
        Text(spaceX.flight_number)
        Text(spaceX.name)
      }
      .navigationBarTitle("SpaceX")
  }
  .onAppear {
      let url = URL(string: "https://api.spacexdata.com/v4/launches/latest")!

      self.fetch(url, defaultValue: SpaceX.default) {
          self.spaceX.name = $0.name
          self.spaceX.flight_number = $0.flight_number
      }
  }
}

and that should return the number and name.

PS you need to add ContentView(spaceX: SpaceX.default) to Previews etc to get rid of errors

3      

Hey thanks for the help.

Was looking at it and tried different things. I'm at the point where I understand concepts on their own but putting things together is the tricky part.

Appreciate the time.

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.