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

SOLVED: A problem with URLSession and JSON fetch

Forums > SwiftUI

Hello everyone,

I've been following along the bit of code Paul published in this post (https://www.hackingwithswift.com/books/ios-swiftui/sending-and-receiving-codable-data-with-urlsession-and-swiftui) on December 2019, and when I change the JSON URL I got this: nw_protocol_get_quic_image_block_invoke dlopen libquic failed

Now:

1) of course I have a struct with the exact same variables you find in the JSON (not all of them, but neither had Paul in his example) 2) you don't even get to bother the codebale struct, you fail to fetch not when parsing. Here:

URLSession.shared.dataTask(with: request) { data, response, error in
    // step 4
}.resume()

3) I read everywhere this is just a "console noise" but not for me... because JSON isn't either fechted or parsed, the app freezes. 4) very same code but the iTunes url that Paul used as an example and everything works great; I started wondring whether is the JSON itself... but of course I cannot change somebody else's API... 5) I am not enrolled in Apple Dev program, could be that? I seriously doubt it, but I'm giving you every thing I have on my own plate

I tried many JSONs: Wordpress's REST service, mock.io and so on. In fact I suggest you to run the code with this super simple JSON (https://jsonplaceholder.typicode.com/todos)

Here's what I've done, you can see this is pretty much Paul's code, I didn't even delete his comments:

struct Response: Codable {
    var results: [Result]
}

struct Result: Codable {
    var userId: Int
    var id: Int
    var title: String
    var completed: Bool
}

struct ContentView: View {
    @State private var results = [Result]()

    let jsonURL = "https://jsonplaceholder.typicode.com/todos"

    var body: some View {
        List(results, id: \.id) { item in
            VStack(alignment: .leading) {
                Text("UID: \(item.userId)")
                    .font(.headline)
                Text("title: \(item.title)")
            }
        }.onAppear(perform: {
            loadData(fromURL: jsonURL)
        })
    }

    func loadData(fromURL url:String) {
        guard let url = URL(string: url) else {
            print("Invalid URL")
            return
        }

        let request = URLRequest(url: url)

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    // we have good data – go back to the main thread
                    DispatchQueue.main.async {
                        // update our UI
                        self.results = decodedResponse.results
                    }

                    // everything is good, so we can exit
                    return
                }
            }

            // if we're still here it means there was a problem
            print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
        }.resume()
    }

}

2      

Your structs are not correct for the JSON returned by https://jsonplaceholder.typicode.com/todos.

You are trying to decode into a Response struct that contains an array of [Result] items with a key of results. But the JSON returns by that URL just has an array at its root, no results key.

In other words, you are trying to decode JSON that looks like this:

{
  "results": [
      {
        "userId": 1,
        "id": 1,
        "title": "delectus aut autem",
        "completed": false
      },
      {
        "userId": 1,
        "id": 2,
        "title": "quis ut nam facilis et officia qui",
        "completed": false
      },
      etc...
}

but you are actually receiving JSON that looks like this:

[
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "quis ut nam facilis et officia qui",
    "completed": false
  },
  etc...

So instead of this:

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    // we have good data – go back to the main thread
                    DispatchQueue.main.async {
                        // update our UI
                        self.results = decodedResponse.results
                    }

                    // everything is good, so we can exit
                    return
                }
            }

you should have this:

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode([Result].self, from: data) {
                    // we have good data – go back to the main thread
                    DispatchQueue.main.async {
                        // update our UI
                        self.results = decodedResponse
                    }

                    // everything is good, so we can exit
                    return
                }
            }

3      

I do feel stupid now. Thanks :D s.

2      

Don't feel stupid, I tripped over that EXACT scenario and it took for FOREVER to come to that same realization.

This is how we learn. 👊🏼

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

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.