1

I am having problems finding out why my dataTask returns an empty result. While going through My NetworkingManager class it appeared that it never enters the URLSession.shared.dataTask. Does anyone know why?

Her is my NetworkingManager which is being used in the ContentView of the app:

class NetworkingManager: ObservableObject {
    var didChange = PassthroughSubject<NetworkingManager, Never>()
    
    var showList = ShowResultsAPI(results: []) {
        didSet {
            didChange.send(self)
        }
    }
    
    init() {
        guard let url = URL(string:  "www.json.url") else {
            return }
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            guard let data = data else {
                return }
            
            let showList = try! JSONDecoder().decode(ShowResultsAPI.self, from: data)

            DispatchQueue.main.async {
                self.showList = showList
            }

        }.resume()
    }
}

Boglinger
  • 15
  • 6
  • Unrelated to your question, but why are you trying to recreate what `@Published` already does for you automatically? Simply mark `showList` as `@Published` and you can get rid of your `PassthroughSubject` and `didSet`. – Dávid Pásztor Mar 24 '20 at 12:36
  • Indeed, thank you for pointing that out! Changed it to @Published. – Boglinger Mar 27 '20 at 15:22

3 Answers3

1

In my opinion your coding looks correct. Keep in mind that the request is asynch. When your debugging the URLSession.shared.dataTask you will recognize that at first the debugger is skipping the dataTask. When the URLSession receives a response it will enter the URLSession.shared.dataTask again. I would recommend to set a breakpoint in the line with your guard statement. Then debug the process again and see if the debugger enters the process.

It would also be interesting to observe the response and the error in the completion handler to see if there are errors occuring.

     URLSession.shared.dataTask(with: url) { (data, response, error) in
       if let error = error {
            print(error)
            return
        }
        guard let httpResponse = response as? HTTPURLResponse,
                    httpResponse.statusCode == 200,
                    let data = data
                    else {
                        print("ResponseProblem")
                        print(response)
                        return
                }
lukas
  • 194
  • 2
  • 8
  • Thank you Lukas for sharing your answer. Indeed, when I set a breakpoint at guard or at the URLSession.shared.dataTask the app breaks at these points as aspect. Any breakpoint set after is not reached as beforehand the app crashes due to an "Index out of range" error by trying to use one showList value in the ContentView (networkingManager.showList.results[0].current.name for example). I wonder when the init of my NetworkingManager returns to the ContentView as I am unable to reach any other segment of the init after the URLSession (no print statements before any return are outputted). – Boglinger Mar 27 '20 at 15:36
-2

Adding a .sleep(2) at the end of the init() helped to process the JSON.

Edited:

It needed an asynchronous task which implies having a sleep or as @vadian suggested a better suited delay() from combine.

Boglinger
  • 15
  • 6
  • When possible, please make an effort to provide additional explanation instead of just code. Such answers tend to be more useful as they help members of the community and especially new developers better understand the reasoning of the solution, and can help prevent the need to address follow-up questions. – Rajan May 14 '20 at 11:41
  • 2
    `sleep` is the worst choice because it blocks the thread. As you are using Combine anyway, there is `delay` or other operators. – vadian Sep 03 '21 at 08:30
-2

add return value in guard : return "example"

change your code to this :

  }

    }.resume()
     sleep(2)
}
salvo720
  • 166
  • 1
  • 4