-1

I am creating an app that connects to an online API. So I created a class which has a function that handles the API call, grabs the data and returns the data after "task.resume()". I need it to return the data because in viewController I created an instance of the API class, run the function call to get the data and then I want to populate my view with that data.

Problem is that inside the function call of my API class I have a guard let else {return} which breaks out of the function if the url is faulty. Swift compiler throws this error: "Non-void function should return a value" but I dont want it to, I just want it to break out of the function.

Im not sure if this is the right way to go about doing this.

class NasaPOD {
    
    var nasaPODdata: NasaData?
        
    func getPOD() -> NasaData {

        ...

        guard var URL = URL(string: "https://api.nasa.gov/planetary/apod") else {return}
        ...

                guard let jsonData = data else {return}
                
                do {
                    self.nasaPODdata = try JSONDecoder().decode(NasaData.self, from: jsonData)
                    //print(self.nasaPODdata!.explanation)
                    //print(self.nasaPODdata!.title)
                    //print(self.nasaPODdata!.hdurl)
                }catch{
                    print(error)
                }
            }
            else {
                // Failure
                print("URL Session Task Failed: %@", error!.localizedDescription);
            }
        })
        task.resume()
        session.finishTasksAndInvalidate()
        return self.nasaPODdata!
    }
}
JeremyRaven
  • 119
  • 1
  • 10
  • 2
    You _cannot return a value_ from a function that gets that value by networking. Your entire architecture is wrong. The cheating use of an instance property is not a solution! You need a _completion handler_. – matt Mar 31 '21 at 22:26
  • Read http://www.programmingios.net/returning-a-value-from-asynchronous-code/ and the two articles that precede it. – matt Mar 31 '21 at 22:34
  • awesome thanks Matt – JeremyRaven Mar 31 '21 at 22:43

1 Answers1

1

As @matt said, you can't just return your response from inside a closure. Check if that works;

func getPOD(closure: @escaping ( _ response: NasaData?) -> Void) {
        guard var URL = URL(string: "https://api.nasa.gov/planetary/apod") else {
            closure(nil)
            return
        }

        guard let jsonData = data else {
            closure(nil)
            return
        }
                
        do {
            self.nasaPODdata = try JSONDecoder().decode(NasaData.self, from: jsonData)
            closure(self.nasaPODdata)
        }catch{
            print(error)
        }
     })
     task.resume()
     session.finishTasksAndInvalidate()
}

And here’s how to call it;

objectOfClass.getPOD { response in
            
}
Sotiris Kaniras
  • 520
  • 1
  • 12
  • 30