Search code examples
iosjsonswiftweather-apiopenweathermap

Swift - How to get OpenWeatherMap JSON Data?


The following app should get the user's current location and then display the Name and Temperature of that location using OpenWeatherMap.

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    @IBOutlet weak var location: UILabel!
    @IBOutlet weak var temperature: UILabel!

    var locationManager: CLLocationManager = CLLocationManager()
    var startLocation: CLLocation!

    func extractData(weatherData: NSData) {
        let json = try? NSJSONSerialization.JSONObjectWithData(weatherData, options: []) as! NSDictionary

        if json != nil {
            if let name = json!["name"] as? String {
                location.text = name
            }

            if let main = json!["main"] as? NSDictionary {
                if let temp = main["temp"] as? Double {
                    temperature.text = String(format: "%.0f", temp)
                }
            }
        }
    }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let latestLocation: AnyObject = locations[locations.count - 1]

        let lat = latestLocation.coordinate.latitude
        let lon = latestLocation.coordinate.longitude

        // Put together a URL With lat and lon
        let path = "http://api.openweathermap.org/data/2.5/weather?lat=\(lat)&lon=\(lon)&appid=2854c5771899ff92cd962dd7ad58e7b0"
        print(path)            

        let url = NSURL(string: path)

        let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in
            dispatch_async(dispatch_get_main_queue(), {
                self.extractData(data!)
            })
        }

        task.resume()
    }

    func locationManager(manager: CLLocationManager,
        didFailWithError error: NSError) {

    }

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        startLocation = nil
    }
}

I've been learning how to get data from OpenWeatherMap following this tutorial: https://www.youtube.com/watch?v=r-LZs0De7_U

The app crashes at:

self.extractData(data!)

as data is equal to nil, this shouldn't be happening as when I copy and paste the printed path into my web browser, the data is there. I'm sure I've followed the tutorial correctly, so what's the problem and how do I fix it?


Solution

  • The problem is with Transport Security - which causes issues for lots of us. Here's one of the SO answers explaining how to resolve it Transport security has blocked a cleartext HTTP

    If you make the setting in your plist - set the NSAllowsArbitraryLoads key to YES under NSAppTransportSecurity dictionary in your .plist file - then it works.