CLLocationManager() Location is nil in simulator - ios

I'm try to get latitude and longitude but location is always nil.
class FinalizeOrderController: UIViewController {
var locManager = CLLocationManager()
var currentLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
currentLocation = CLLocation()
locManager.requestWhenInUseAuthorization()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func FinaliseOrder(_ sender: Any) {
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {
currentLocation = locManager.location
print(locManager.location?.coordinate.latitude) //prints nil
print(currentLocation.coordinate.longitude) //fatal error: unexpectedly found nil while unwrapping an Optional value
}
lbl1.text = "\(currentLocation.coordinate.longitude)"
lbl2.text = "\(currentLocation.coordinate.latitude)"
}
I add info.plist keys and run simulator location from Xcode and chooses simulator location from debug but no way always nil

Try this :
var locationManager: CLLocationManager?
var currentLocation:CLLocation?
Conform Delegate
class ViewController: UIViewController,CLLocationManagerDelegate
In ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager();
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest
let authorizationStatus = CLLocationManager.authorizationStatus()
if (authorizationStatus == CLAuthorizationStatus.NotDetermined) {
locationManager.requestWhenInUseAuthorization()
} else {
locationManager.startUpdatingLocation()
}
}
In Delegate
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
currentLocation = locations[locations.count-1] as CLLocation
print("locations = \(currentLocation)")
// lbl1.text = "\(currentLocation.coordinate.latitude)";
// lbl2.text = "\(currentLocation.coordinate.longitude)";
}
In button action
#IBAction func FinaliseOrder(_ sender: Any) {
lbl1.text = "\(currentLocation.coordinate.longitude)"
lbl2.text = "\(currentLocation.coordinate.latitude)"
}

Related

Swift - Location Prompt not happening soon enough

I am building a location-based app that lists nearby coffee houses. App keeps crashing on first build on device because location keeps returning as nil.
This is because the Privacy - Location prompt isn't happening soon enough, even though though the request is earlier in the code. After I close the app after it crashes, that's when I'm prompted to allow my location.
I have three onboarding screens, and when I get to this tableviewcontroller, that's when it crashes.
If I go into Settings > Privacy > Location and manually enable location services, the app works great.
Here's my code (I removed a ton of unnecessary stuff):
import UIKit
import MapKit
import CoreLocation
class ShopTableViewController: UITableViewController, CLLocationManagerDelegate {
#IBAction func filterBack(_ sender: Any) {
getLocale()
shops.sort() { $0.distance < $1.distance }
shops.removeAll()
loadShops()
sortList()
}
//MARK: Properties
var shops = [CoffeeShop]()
var filteredShops = [CoffeeShop]()
var objects: [CoffeeShop] = []
var locationManager = CLLocationManager()
func checkLocationAuthorizationStatus() {
if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
locationManager.requestWhenInUseAuthorization()
}
}
var currentLocation = CLLocation!.self
var userLatitude:CLLocationDegrees! = 0
var userLongitude:CLLocationDegrees! = 0
var locValue:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 1.0, longitude: 1.0)
var refresher: UIRefreshControl! = UIRefreshControl()
func getLocale() {
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locationManager.startMonitoringSignificantLocationChanges()
userLatitude = self.locationManager.location?.coordinate.latitude
userLongitude = self.locationManager.location?.coordinate.longitude
print("\(userLatitude), \(userLongitude)")
}
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager = CLLocationManager()
/// self.locationManager.requestWhenInUseAuthorization()
checkLocationAuthorizationStatus()
self.locationManager.delegate = self
self.locationManager.startUpdatingLocation()
if CLLocationManager.locationServicesEnabled()
{
getLocale()
}
let locValue = self.locationManager.location?.coordinate
noHeight()
loadShops()
sortList()
print("\(locValue?.latitude), \(locValue?.longitude)")
refresher = UIRefreshControl()
refresher.addTarget(self, action: #selector(ShopTableViewController.handleRefresh), for: UIControlEvents.valueChanged)
if #available(iOS 10, *) {
shopTable.refreshControl = refresher
} else {
shopTable.addSubview(refresher)
}
}
}
What am I doing wrong?
requestWhenInUseAuthorization() is an asynchronous method, so your method that wraps it checkLocationAuthorizationStatus() is also async.
However, in your viewDidLoad, you call
checkLocationAuthorizationStatus()
self.locationManager.delegate = self
self.locationManager.startUpdatingLocation()
This is triggering the locationManager to start before it is authorized. Take a look here at this (somewhat old) link http://nshipster.com/core-location-in-ios-8/
Example
Be sure to conform to CLLocationManagerDelegate
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager = CLLocationManager()
self.locationManager.delegate = self
if CLLocationManager.authorizationStatus() == .notDetermined {
locationManager.requestWhenInUseAuthorization()
} else if CLLocationManager.authorizationStatus() == . authorizedWhenInUse {
startTrackingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedAlways || status == .authorizedWhenInUse {
startTrackingLocation()
// ...
}
}
func startTrackingLocation() {
locationManager.startUpdatingLocation()
getLocale()
//not clear which of these methods require location
let locValue = self.locationManager.location?.coordinate
noHeight()
loadShops()
sortList()
print("\(locValue?.latitude), \(locValue?.longitude)")
}
You need to wait for the authorization response before using location services.
What you are doing now is requesting the authorization and the immediately starting location services. You need to be sure, the app is authorized before getting location.

iOS swift Location Manager not getting updated properly

I am using CLLocationManager for getting user location. I need to update user location when they move. I am using this code :
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
private var locationManager = CLLocationManager()
lazy var locations = [CLLocation]()
var op:String = ""
#IBOutlet weak var resultTxt: UITextView!
#IBAction func Start(sender: AnyObject) {
startLocationManager()
showResult()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func startLocationManager(){
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
func startLocationTracking() {
NSLog("startLocationTracking")
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .NotDetermined, .Restricted, .Denied:
print("No access")
self.startLocationManager()
case .AuthorizedAlways, .AuthorizedWhenInUse:
NSLog("authorizationStatus authorized")
}
} else {
print("Location services are not enabled")
self.startLocationManager()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for location in locations {
let howRecent = location.timestamp.timeIntervalSinceNow
if abs(howRecent) < 10 && location.horizontalAccuracy < 20 {
//update distance
self.locations.append(location)
showResult()
}
}
}
func showResult(){
let currentDate = NSDate()
let res:String = "Result LAT : \(self.locations.last?.coordinate.latitude) AND LNG : \(self.locations.last?.coordinate.longitude) Time : \(currentDate.toShortTimeString()) \n "
op += res
self.resultTxt.text = op
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
And I have already added NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription in .plist.
This code works fine for the first time. But when the user moves "didUpdateLocations" is not getting fired.
Can any one please help me, what I am doing wrong?
Try to add these lines, to be able to monitoring significant location changes when user moves:
locationManager.startMonitoringSignificantLocationChanges()
locationManager.distanceFilter = 300 //value is up to you

location constantly updating problems iOS Swift

I am getting the users current location and dropping this as a println(). The idea is that I am going to hit a button to get the new location, however currently the app keeps updating constantly (every second) instead. I have tried moving the getLocation() function inside my IBAction but that crashed the thing. I have updated the info.plist so thats not a problem. Heres le code:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
#IBOutlet var latitude : UILabel!
#IBOutlet var longitude : UILabel!
var locationManager = CLLocationManager()
var startLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func findMyLocation(sender: AnyObject){
startLocation = nil
locationManager.startUpdatingLocation()
}
func getLocation(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
var userLocation:AnyObject = locations[0] as! CLLocation
var strlat = String(format: "%.4f", userLocation.coordinate.latitude)
var strlong = String(format: "%.4f",userLocation.coordinate.longitude)
latitude.text = String(format: "%.4f", userLocation.coordinate.latitude)
longitude.text = String(format: "%.4f",userLocation.coordinate.longitude)
println("latitude: " + strlat)
println("longitide: " + strlong)
if startLocation == nil {
startLocation = userLocation as! CLLocation
locationManager.stopUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager!,
didFailWithError error: NSError!) {
}
}
Move the locationManager.startUpdatingLocation() to your findMyLocation function. This will start the locationManager when your button is pressed and begin calling the didUpdateLocations Inside your if startLocation == nil add locationManager.stopUpdatingLocation() this will stop the locationManager after you have set your startLocation var. Every time the user presses the button the process will run again.
One additional note, you should add more code into the didUpdateLocations to check the accuracy and timestamp of the location before you use it as it may not be a valid/accurate location for what you are trying to do.
UPDATE:
Had a chance to validate and the code will work with the changes suggested. Here is what your final code should look like. I am also assuming you have set your plist entries for locations services and your simulator is set to simulate locaitons.
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
#IBOutlet var latitude : UILabel!
#IBOutlet var longitude : UILabel!
var locationManager : CLLocationManager! = CLLocationManager()
var startLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func findMyLocation(sender: AnyObject){
startLocation = nil
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
var userLocation:AnyObject = locations[0] as! CLLocation
var strlat = String(format: "%.4f", userLocation.coordinate.latitude)
var strlong = String(format: "%.4f",userLocation.coordinate.longitude)
latitude.text = String(format: "%.4f", userLocation.coordinate.latitude)
longitude.text = String(format: "%.4f",userLocation.coordinate.longitude)
println("latitude: " + strlat)
println("longitide: " + strlong)
if startLocation == nil {
startLocation = userLocation as! CLLocation
locationManager.stopUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("error with location manager: " + error.description)
}
}

IOS 8 swift CoreLocation

Im learning Xcode 6.3 and swift and following a book from apress Beginning Xcode with swift, in chapter 4 when doing the first tab for the location tracker it shows nothing at all and I'm confused. The code for the first tab is this
import UIKit
import CoreLocation
class TrackViewController: UIViewController, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
#IBOutlet weak var locationText: UITextView!
#IBOutlet weak var toggleSwitch: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func changeToggle(sender: UISwitch) {
if toggleSwitch.on {
self.locationText.text = " "
if (CLLocationManager.locationServicesEnabled() == false) {
self.toggleSwitch.on = false
}
if locationManager == nil {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.distanceFilter = 10.0
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestWhenInUseAuthorization()
UIApplication.sharedApplication().cancelAllLocalNotifications()
NSLog("location is on supposely")
}
locationManager.startUpdatingLocation()
} else {
if locationManager != nil {
locationManager.stopUpdatingLocation()
}
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var location: CLLocation = locations[locations.endIndex - 1] as! CLLocation
self.locationText.text = location.description
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationText.text = "failed with error \(error.description)"
}
}
I have activated in the simulator the location services and in info.plist added the NSLocationWhenInUsageDescription and the Privacy - Location..., but nothing happens when toggling the switch I get no feedback that something is on. Any help??

Trying to find users location in Xcode with Swift on starting the app but having optional error?

I'm attempting to have the app find the user's location once the app has been started. However, I continually find an error in the viewDidLoad method as I try to requestWhenInUseAuthorization and I receive the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
I would be really grateful if anyone could help me find a solution to this problem. Thanks!
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var lastLocation = CLLocation()
var locationAuthorizationStatus:CLAuthorizationStatus!
var window: UIWindow?
let locationManager: CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.initLocationManager()
}
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled()) {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
self.initLocationManager()
locationManager.requestWhenInUseAuthorization()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.showsUserLocation = true
mapView.delegate = self
self.mapView.setUserTrackingMode(MKUserTrackingMode.Follow, animated: true);
}
// Location Manager helper stuff
func initLocationManager() {
locationManager.requestWhenInUseAuthorization()
}
// Location Manager Delegate stuff
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if ((error) != nil) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your didload method is getting called before the didAppear method. Therefore, your location manager is not initialized yet. So you need to initialize it before using it.

Resources