HSCKER_
HSCKER_

Reputation: 57

location coordinates return nil in swift

Coordinates return nil, I have entered requestAlwaysAuthorization and requestWhenInUseAuthorization in the plist file, but yet nothing happens. Here is my code.

what is going in this code? I can't find where the error is. It's just returning nil for cordinates

import UIKit
import CoreLocation

class ViewController: UIViewController,CLLocationManagerDelegate {
//Location
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
var locationManager: CLLocationManager!
var userLocation : String!
var userLatitude : Double!
var userLongitude : Double!

//Current weather Outlets "Display Objects"
@IBOutlet weak var userLocationLabel: UILabel!
@IBOutlet weak var visibilityLabel: UILabel!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var iconView: UIImageView!
@IBOutlet weak var currentTimeLabel: UILabel!
@IBOutlet weak var humidityLabel: UILabel!
@IBOutlet weak var precipitationLabel: UILabel!
@IBOutlet weak var summaryLabel: UILabel!
@IBOutlet weak var windSpeedLabel: UILabel!
@IBOutlet weak var refreshButton: UIButton!
@IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!


//API KEY
private let apiKey = "09ca8e3e75fafbadaf4b8594dabe860e"

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from         a nib.
    refreshActivityIndicator.hidden = true
    getCurrentWeatherData()
}


//Location Code

func initLocationManager() {
    seenError = false
    locationFixAchieved = false
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
    locationManager.startUpdatingLocation()    }

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
    locationManager.stopUpdatingLocation()
    if ((error) != nil) {
        if (seenError == false) {
            seenError = true
            print(error)
        }
    }
}

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)->Void in

        let pm = placemarks[0] as! CLPlacemark
        self.displayLocationInfo(pm)
    })

    if (locationFixAchieved == false) {
        locationFixAchieved = true
        var locationArray = locations as NSArray
        var locationObj = locationArray.lastObject as! CLLocation
        var coord = locationObj.coordinate
        self.userLatitude = coord.latitude
        self.userLongitude = coord.longitude

        getCurrentWeatherData()


    }
}


func displayLocationInfo(placemark: CLPlacemark?) {
    if let containsPlacemark = placemark {
        //stop updating location to save battery life
        locationManager.stopUpdatingLocation()
        let locality = (containsPlacemark.locality != nil) ? containsPlacemark.locality : ""
        let postalCode = (containsPlacemark.postalCode != nil) ? containsPlacemark.postalCode : ""
        let administrativeArea = (containsPlacemark.administrativeArea != nil) ? containsPlacemark.administrativeArea : ""
        let country = (containsPlacemark.country != nil) ? containsPlacemark.country : ""
        //println(locality)
        //println(postalCode)
        //println(administrativeArea)
        //println(country)

        self.userLocationLabel.text = "\(locality), \(administrativeArea)"
    }
}


func locationManager(manager: CLLocationManager!,
    didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        var shouldIAllow = false

        switch status {
        case CLAuthorizationStatus.Restricted:
            locationStatus = "Restricted Access to location"
        case CLAuthorizationStatus.Denied:
            locationStatus = "User denied access to location"
        case CLAuthorizationStatus.NotDetermined:
            locationStatus = "Status not determined"
        default:
            locationStatus = "Allowed to location Access"
            shouldIAllow = true
        }
        NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
        if (shouldIAllow == true) {
            NSLog("Location to Allowed")
            // Start location services
            locationManager.startUpdatingLocation()
        } else {
            NSLog("Denied access: \(locationStatus)")
        }
}


func getCurrentWeatherData() -> Void {
    userLocation = "\(userLatitude),\(userLongitude)"

    // DC cord. = "44.029002,-92.855343"
    //URL
    let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
    let forecastURL = NSURL(string:"\(userLocation)", relativeToURL: baseURL)


    // creates data object; to get and save data from online
    let sharedSession = NSURLSession.sharedSession()
    let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location:NSURL!, response:NSURLResponse!, error: NSError!) -> Void in

        // if everything goes alright (no errors then run code)
        if (error == nil) {

            //turn JSON dictionary to NSDictionary so it's easier to work with
            let dataObject = NSData(contentsOfURL: location)
            let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as! NSDictionary

            //bring weather dictionary from the CurrentWeather file
            let currentWeather = Current(weatherDictionary: weatherDictionary)
            println(weatherDictionary)

            //update view with current weather information
            dispatch_sync(dispatch_get_main_queue(), { () -> Void in
                self.temperatureLabel.text = "\(currentWeather.temperature)"
                self.iconView.image = currentWeather.icon!
                self.currentTimeLabel.text = "\(currentWeather.currentTime!)"
                self.humidityLabel.text = "\(currentWeather.humidity * 100)%"
                self.precipitationLabel.text = "\(currentWeather.precipProbability * 100)%"
                self.summaryLabel.text = "\(currentWeather.summary)"
                self.windSpeedLabel.text = "\(currentWeather.windSpeed) MPH"
                self.visibilityLabel.text = "\(currentWeather.visibility) Mi"

                //stop refresh animation
                self.refreshActivityIndicator.stopAnimating()
                self.refreshActivityIndicator.hidden = true
                self.refreshButton.hidden = false
            })
 }

 else {

        let networkIssueController = UIAlertController(title: "Error", message: "Network Connectivity Error! Can't load data", preferredStyle: .Alert)
     println(error)
            //information for ok button in alertView
        let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
        networkIssueController.addAction(okButton)

            //information for cancel button in alertView
        let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
        networkIssueController.addAction(cancelButton)

        //if an error occurs show alert
        self.presentViewController(networkIssueController, animated: true, completion: nil)

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
        //Stop refresh animation
        self.refreshActivityIndicator.stopAnimating()
        self.refreshActivityIndicator.hidden = true
        self.refreshButton.hidden = false

        })

        }
})

    downloadTask.resume()
}
//refresh method
@IBAction func refresh() {
    getCurrentWeatherData()
    refreshButton.hidden = true
    refreshActivityIndicator.hidden = false
    refreshActivityIndicator.startAnimating()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Upvotes: 0

Views: 2245

Answers (2)

MwcsMac
MwcsMac

Reputation: 7168

I struggled with this step as well. And MirekE has pointed out all great points. I have built on what MirekE stated and showed yo some code to maybe help explain it in more detail.
Step 1) Make sure your info.plist have the following.Do not forget to give them a value like - Need to use your location to get the weather for your current location. Or some thing along those lines.
NSLocationAlwaysUsageDescription
Privacy - Location Usage Description
NSLocationWhenInUseUsageDescription

Step 2) I added this code to my project and combined with step 1 then I would get the alert views to allow location services.

        //this is part of my viewDidLoad()
        if ( ios8() ) {
        locationManager.requestAlwaysAuthorization()
        locationManager.requestWhenInUseAuthorization()
    }
    locationManager.startUpdatingLocation()

/*
iOS 8 Utility
*/
func ios8() -> Bool {
    if ( NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1 ) {
        return false
    } else {
        return true
    }
}

Step 3) I used defaults to store them for another purpose.

    // MARK: CLLocationManagerDelegate
public func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    var location:CLLocation = locations[locations.count-1]as! CLLocation

    if (location.horizontalAccuracy > 0) {
        self.locationManager.stopUpdatingLocation()
        self.defaults.setDouble(location.coordinate.latitude, forKey: "lat")
        self.defaults.setDouble(location.coordinate.longitude, forKey: "lon")
        println("lat \(location.coordinate.latitude)  lon \(location.coordinate.longitude)")
        defaults.synchronize()
        updateLocationInfo() // This is where you would call your getCurrentWeatherData()      

    }
}
// MARK: locationManager
public func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
    println(error)
    self.loading.text = "Can't get your location!"
}

Upvotes: 1

MirekE
MirekE

Reputation: 11555

Perhaps you already handled all these situations in code that is not shown, but here is a list of things that I think are missing in your code:

  • I don't think you call initLocationManager in your code.
  • getCurrentWeatherData() in your viewDidLoad() won't work, you need to call it from locationManager(didUpdateLocations).
  • Adding requestAlwaysAuthorization or requestWhenInUseAuthorization alone to the application options is not enough. You also need to provide NSLocationAlwaysUsageDescription with text explaining why you need access.
  • You need to check the authorization status. If it is undetermined, you need to request access and implement a callback to wait for user response. If you call requestAuthorization with any other status than undetermined, I believe the function does not do anything and does not provide any feedback.
  • For further troubleshooting I would suggest that you (1) get the status of the authorization and (2) put a print statement or a breakpoint to the locationManager(didUpdateLocations) to see if it gets called at all.

Upvotes: 2

Related Questions