0

I am fairly new to developing apps for iOS, and the Swift language in itself. I'm trying to learn how to make HTTP requests for future projects, but to no avail.

My current approach is through using Alamofire and SwiftyJSON, which is configured through Cocoapods. The code below is for a class which sends a GET request to openweathermap.org, which given the name for a city, returns JSON that contains the current temperature of the city.

However, it seems that no matter what I input as the city name (see second-last line), the only thing printed in the last line is 0.0. Through inspection of the .playground file I put this in, the request doesn't seem to activate at all - the value never changes from the default value I set it, Float(0).

import Alamofire
import SwiftyJSON

// City temperature class: given a city name, the class will
// automatically generate the city's temperature.
class City {
    var name: String
    var temperature: Float

    // Helper function, get request through Alamofire is here
    private func getTemperature(completionHandler: @escaping (Error?, String?) -> ()) {
        let key = "" // Insert key for openweathermap.org here
        let url = "https://api.openweathermap.org/data/2.5/weather?q=\(self.name)&units=metric&appid=\(key)"

        Alamofire.request(url, method: .get).responseJSON { response in
            switch response.result {
            case .success(let value):
                completionHandler(nil, value as? String)
            case .failure(let error):
                completionHandler(error, nil)
            }
        }
    }

    // Initialisation function, this will call getTemperature()
    // to set self.temperature
    init(name: String) {
        // All class variables have to be set - if not set,
        // Xcode refuses to run playground file
        self.name = name
        self.temperature = Float(0)

        getTemperature { (error, response) in
            if error == nil {
                let json = JSON(response as String!)
                self.temperature = json["main"]["temp"].float!
            } else {
                print(error!.localizedDescription)
            }
        }
    }
}

let city = City(name: "Sydney")
print(city.temperature) // Doesn't matter what name I put in, output is always 0.0
Qwerp-Derp
  • 487
  • 7
  • 20
  • Of course it's 0 because `Alamofire.request` works asynchronously (result is returned later). Put the print line in the completion handler of `getTemperature `. It's a bad idea anyway to put an asynchronous task in an `init` method – vadian Jan 06 '18 at 12:44
  • @vadian: Well, how else should I do this, so that `self.temperature` is updated when I initialise the class? Or is that completely impossible? I have a feeling I phrased this question pretty badly... – Qwerp-Derp Jan 06 '18 at 12:46
  • If you want to process the result, init the class (do you really need a class?), then call `getTemperature` and use the completion handler to update the UI or whatever. – vadian Jan 06 '18 at 12:49
  • @vadian So you're saying that it's basically impossible to do what I want to achieve then, right? Swift's HTTP requests are pretty different from what I've experienced, to say the least. Thanks! – Qwerp-Derp Jan 06 '18 at 12:51
  • It's impossible to get a result from an asynchronous task in an `init` method. Please learn to understand how asynchronous networking works. Asynchronous data processing is a very essential pattern (not only in Swift). – vadian Jan 06 '18 at 12:54
  • @vadian Thanks for offering a completely non-passive-agressive remark! This is what I love about Stack Overflow, it's the friendly attitude that everyone has! If I'm doing something completely stupid, can you at least try to be a little patient? – Qwerp-Derp Jan 06 '18 at 12:55
  • Alamofire (and no HTTP requests are any different, so the comment about "Swift's ... are pretty different" makes no sense) is an asynchronous task (which means you will send a request and LATER get a response) so you need to look at the response when it comes in. You should study up on asynch... https://stackoverflow.com/questions/27390656/how-to-return-value-from-alamofire shows how to do this properly. – Apps-n-Add-Ons Jan 06 '18 at 13:01
  • @CFPSupport Thanks for the response, I'll read up on async. – Qwerp-Derp Jan 06 '18 at 13:06

0 Answers0