Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
132 views
in Technique[技术] by (71.8m points)

ios - How to pass data from an API call to the ViewController?

I built an APIManager class that has function to make API calls to my API that is working fine. Then I use a class APIClient to store every calls that I need to do on my API with the specific parameters such as url queries or POST data.

The problem is that these function are void functions and return nothing. I'm wondering how I can modify this to return data that I can store in a variable in my ViewController.

Here is the function that I use in APIManager:

func makeRequest(toURL url: URL,
                     withHttpMethod httpMethod: HttpMethod,
                     completion: @escaping (_ result: Results) -> Void) {
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            let targetURL = self?.addURLQueryParameters(toURL: url)
            let httpBody = self?.getHttpBody()
            
            guard let request = self?.prepareRequest(withURL: targetURL, httpBody: httpBody, httpMethod: httpMethod) else
            {
                completion(Results(withError: CustomError.failedToCreateRequest))
                return
            }
            
            let sessionConfiguration = URLSessionConfiguration.default
            let session = URLSession(configuration: sessionConfiguration)
            let task = session.dataTask(with: request) { (data, response, error) in
                completion(Results(withData: data,
                                   response: Response(fromURLResponse: response),
                                   error: error))
            }
            task.resume()
        }
    }

Then in my ViewController I define my APIClient and calls one function on button tap :

let apiClient = APIClient()
@IBAction func testTapped(_ sender: Any) {
        apiClient.getData()
    }

and then my APIClient handles the call :

func getData() {
        var decodedResponse: Any?
        guard let url = URL(string: "https://XX.API.XX/XX//XXX/XXX/XXX") else { return }
        apiManager.makeRequest(toURL: url, withHttpMethod: .get) { (results) in
            guard let response = results.response else { return }
            if response.httpStatusCode == 200 {
                guard let data = results.data else { return }
                let decoder = JSONDecoder()
                guard let decodedData = try? decoder.decode(Data.self, from: data) else { return }
            }
        }
    }

Does anybody has a clue on which way I can modify these files so I can return decodedDatafrom APIClient and store it in my ViewController ?

question from:https://stackoverflow.com/questions/66064562/how-to-pass-data-from-an-api-call-to-the-viewcontroller

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you need to get the result in your view controller, one of the ways to achieve this is passing it back through a callback, just like you're passing the result from your manager to the APIClient.

func getData(completion handler: @escaping (Data?, Error?) -> Void) {
        var decodedResponse: Any?
        guard let url = URL(string: "https://XX.API.XX/XX//XXX/XXX/XXX") else { return }
        apiManager.makeRequest(toURL: url, withHttpMethod: .get) { (results) in
            guard let response = results.response else { return }
            if response.httpStatusCode == 200 {
                guard let data = results.data else { return }
                let decoder = JSONDecoder()
                guard let decodedData = try? decoder.decode(Data.self, from: data) else { 
                   handler(NSError(code: 1, ...)) /// <===
                   return
                }
               handler(decodedData)  /// <===
            } else {
               handler(results.error) /// <===
            } 
        }
    }
@IBAction func testTapped(_ sender: Any) {
    apiClient.getData { data, error in
        if let data = data {
             //do anything with the data
        } else if let error = error {
             //show the error message
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...