Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMohsen Lotfi
2,694 PointsHow to get current location on ViewDidLoad
I think I finally figured out the location challenge, However, on Xcode and when debugging, location value gets update only if I click refresh button. before that I am getting 0.0 (initial value) for both lat and long
Would appreciate any feedback on this
here is my code
import UIKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate {
@IBOutlet weak var iconView: UIImageView!
@IBOutlet weak var currentTimeLabel: UILabel!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var humadityLabel: UILabel!
@IBOutlet weak var precipitationLabel: UILabel!
@IBOutlet weak var summaryLabel: UILabel!
@IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!
@IBOutlet weak var refreshButton: UIButton!
private let apiKey = "#################"
let locationManager = CLLocationManager()
var locationLat: Double = 0
var locationLong: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
getCurrentWeatherData()
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.requestAlwaysAuthorization()
if (CLLocationManager.locationServicesEnabled())
{
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
//Print out location after viewDidLoad()
println("on viewDidLoad Location is \(locationLat) and \(locationLong)")
refreshActivityIndicator.hidden = true
super.viewDidLoad()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var locValue:CLLocationCoordinate2D = manager.location.coordinate
locationLat = locValue.latitude
locationLong = locValue.longitude
}
func getCurrentWeatherData() -> Void {
var currentLat = locationLat
var CurrentLon = locationLong
//printout Location inside function
println("inside func location is \(currentLat) and \(CurrentLon)")
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
let forecastURL = NSURL(string: "\(currentLat),\(CurrentLon)/", relativeToURL:baseURL!)
let sharedSession = NSURLSession.sharedSession()
let downloadTask : NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location :NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.temperatureLabel.text = "\(currentWeather.temprature)"
self.iconView.image = currentWeather.icon!
self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
self.humadityLabel.text = "\(currentWeather.humadity)"
self.precipitationLabel.text = "\(currentWeather.precipProbability)"
self.summaryLabel.text = "\(currentWeather.summary)"
// stop refresh process
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
} else {
let networkIssueController = UIAlertController(title: "Ooops", message: "Something went seriously wrong!...Nope, Just enable WiFi Again" , preferredStyle: .Alert)
self.presentViewController(networkIssueController, animated: true, completion: nil)
let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
networkIssueController.addAction(okButton)
let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
networkIssueController.addAction(cancelButton)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
downloadTask.resume()
}
@IBAction func refresh() {
refreshButton.hidden = true
refreshActivityIndicator.hidden = false
refreshActivityIndicator.startAnimating()
getCurrentWeatherData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
here is the println console output
inside func location is 0.0 and 0.0
on viewDidLoad Location is 0.0 and 0.0
inside func location is 35.7020691 and 139.7753269
3 Answers
Mohsen Lotfi
2,694 Pointso.k I I figured it out, here is the answer if anyone is interested, needed to add these two bad boys in viewDidLoad
locationLat = locationManager.location.coordinate.latitude
locationLong = locationManager.location.coordinate.longitude
Now you need to be careful with this as it might cause a runtime error since apparently it can take couple of seconds to get the location update from GPS and this might return nil. to prevent it you can add optional unwrapping and repeat the process to get a value.
As a bonus, following is also reverse geodecoder that I added to get the location based on current coordinates. Shoutout to whoever I copied it from (SO post I guess)
var location = CLLocationManager()
CLGeocoder().reverseGeocodeLocation(location.location, completionHandler: {(placemarks, error) -> Void in
if error != nil {
println("Reverse geocoder failed with error" + error.localizedDescription)
return
}
if placemarks.count > 0 {
let pm = placemarks[0] as CLPlacemark
//Printing to console to check value!
println("\(pm.locality)")
println("\(pm.subLocality)")
self.locality = pm.locality as String
if ( pm.subLocality != nil) {
self.subLocality = pm.subLocality as String
}
}
else {
println("Problem with the data received from geocoder")
}
})
Jared Watkins
10,756 PointsThanks for sharing your code.
This didn't work for me. The original values for locationLat and locationLong never change from 0. And the authorization requests aren't ever triggered triggered.
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.requestAlwaysAuthorization()
if (CLLocationManager.locationServicesEnabled())
{
locationManager.delegate = self.locationManager.delegate
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
Also, I can't see that the locationManager() function is ever called or doing anything.
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var locValue:CLLocationCoordinate2D = manager.location.coordinate
locationLat = locValue.latitude
locationLong = locValue.longitude
}
Mohsen Lotfi
2,694 PointsPrevious code was intended to show how to get the location on viewDidLoad, it certainly has some performance and bugs that I still trying to find my way around it. This is the latest improvements. Hope it works for you. Also about the location being 0, As far as I can tell it has to do something with the iOS simulator, for some reason, simulator starts updating location couple of second after the initial viewDidLoad and such cases results in nil as location which can crash the application.
My work around for this was to check and see if the location is either 0 or nil and then restart "start location update". this seems to help with the issue.
import UIKit
import CoreLocation
import SystemConfiguration
class ViewController: UIViewController,CLLocationManagerDelegate {
@IBOutlet weak var iconView: UIImageView!
@IBOutlet weak var currentTimeLabel: UILabel!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var humadityLabel: UILabel!
@IBOutlet weak var precipitationLabel: UILabel!
@IBOutlet weak var summaryLabel: UILabel!
@IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!
@IBOutlet weak var refreshButton: UIButton!
@IBOutlet weak var locationLabel: UILabel!
@IBOutlet weak var subLocationLabel: UILabel!
private let apiKey = "#####################"
let locationManager = CLLocationManager()
var locationLat: Double = 0
var locationLong: Double = 0
var locality: String = ""
var subLocality:String = ""
var refershController = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.requestAlwaysAuthorization()
// if (CLLocationManager.locationServicesEnabled())
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
locationManager.distanceFilter = 100
if locationManager.location != nil {
locationLat = locationManager.location.coordinate.latitude
locationLong = locationManager.location.coordinate.longitude
refresh()
}
// Else below is a duplicate and does not require to be here. It is just extra debug level for observation
else
{
println("Location is Nil ")
refreshActivityIndicator.hidden = true
refresh()
func LocationManagers(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
locationLat = manager.location.coordinate.latitude
locationLong = manager.location.coordinate.longitude
refresh()
}
}
refreshActivityIndicator.hidden = true
refresh()
super.viewDidLoad()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var locValue:CLLocationCoordinate2D = manager.location.coordinate
var currentLocation = CLLocation()
self.locationLat = locValue.latitude
self.locationLong = locValue.longitude
}
// func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
// println("error + " + error.localizedDescription)
// }
func getCurrentWeatherData() -> Void {
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
let forecastURL = NSURL(string: "\(locationLat),\(locationLong)/",
relativeToURL:baseURL!)
let sharedSession = NSURLSession.sharedSession()
let downloadTask : NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location :NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil) {
self.refreshButton.hidden = true
self.refreshActivityIndicator.hidden = false
self.refreshActivityIndicator.startAnimating()
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.temperatureLabel.text = "\(currentWeather.temprature)"
self.iconView.image = currentWeather.icon!
self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
self.humadityLabel.text = "\(currentWeather.humadity)"
self.precipitationLabel.text = "\(currentWeather.precipProbability)"
self.summaryLabel.text = "\(currentWeather.summary)"
// stop refresh process
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
self.locationLabel.text = "\(self.locality)"
self.subLocationLabel.text = "\(self.subLocality)"
})
} else {
let networkIssueController = UIAlertController(title: "Ooops", message: "Something went seriously wrong!...Nope, Just enable WiFi Again" , preferredStyle: .Alert)
self.presentViewController(networkIssueController, animated: true, completion: nil)
let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
networkIssueController.addAction(okButton)
let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
networkIssueController.addAction(cancelButton)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
downloadTask.resume()
}
@IBAction func refresh()
{
if IJReachability.isConnectedToNetwork() {
refreshButton.hidden = true
refreshActivityIndicator.hidden = false
refreshActivityIndicator.startAnimating()
if locationManager.location != nil {
//
// self.locationLat = locationManager.location.coordinate.latitude
// self.locationLong = locationManager.location.coordinate.longitude
//
CLGeocoder().reverseGeocodeLocation(locationManager.location, completionHandler: {(placemarks, error) -> Void in
if error != nil {
println("Reverse geocoder failed with error" + error.localizedDescription)
self.refresh()}
if placemarks.count > 0 {
let pm = placemarks[0] as CLPlacemark
self.locality = pm.locality as String
if ( pm.subLocality != "") {
self.subLocality = pm.subLocality as String}
println("First XXXXGeo \(pm.subLocality)")
self.getCurrentWeatherData()
}
else {
self.locationManager.startUpdatingLocation()
self.refresh()
println("Problem with the data received from geocoder")}
})
}
else {
self.locationManager.startUpdatingLocation()
println("\(locationLat)")
refresh()
}
} else {
self.locationManager.startUpdatingLocation()
println("no Network ")
let networkConnectionController = UIAlertController(title: "No Internet Connectin", message: "This app needs Internet connection to work, Hit refresh to retry" , preferredStyle: .Alert)
self.presentViewController(networkConnectionController, animated: true, completion: nil)
let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
networkConnectionController.addAction(okButton)
let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
networkConnectionController.addAction(cancelButton)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Also I found this on internet (original post http://www.chrisdanielson.com/2009/07/22/iphone-network-connectivity-test-example/) , which does a great job checking for internet connection before the app starts and is a bit more advanced than the one mentioned in the course.
Brian Patterson
19,588 PointsBrian Patterson
19,588 PointsIm struck on the UIAlertView. As this has been deprecated . How do you add the UIAlertViewController? Well done on getting the current location.