1

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?

John Slegers
  • 45,213
  • 22
  • 199
  • 169
simpleguy
  • 273
  • 7
  • 18
  • 1
    **As always:** If an API provides an `error` parameter **first** check that parameter and handle the error. In case of `dataTaskWithURL` if an error occurs, `data` is `nil`, if there is no error, `error` is `nil` and `data` is valid. **NEVER EVER** forced unwrap optionals when receiving data from the network. – vadian Mar 02 '16 at 17:47
  • I understand that, but in this situation, why am I not getting the data in the first place. – simpleguy Mar 02 '16 at 17:52
  • Once again: Handle the error, I guess it's an ATS (App Transport Security) issue. – vadian Mar 02 '16 at 17:54
  • @vadian I shoudn't have to as this shouldn't normally happen. Skip to 16:34 of the video, my code is the same bar a few changes due to swift updates. Why does it work for him but not me? – simpleguy Mar 02 '16 at 18:00
  • You seem to be immune to suggestions: What error do you get? – vadian Mar 02 '16 at 18:02
  • as shown in the start of video demo uses xcode 6.2, which will have iOS 8.2, the ATS has come with iOS 9/xcode 7. so if you try it with the latest xcode/device you need to add ATS additionally than the video instructions – HardikDG Mar 02 '16 at 18:05

1 Answers1

3

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.

Community
  • 1
  • 1
Russell
  • 5,436
  • 2
  • 19
  • 27