Swift CoreLocation - swift

For the following line of code:
let currentLocationCoordinates = locationManager.requestLocation()
I get this warning:
Constant 'currentLocationCoordinates' inferred to have type 'Void',
which may be unexpected
In Info.plist I added this Keys:
Privacy - Location Always and When In Use Usage Description
Privacy - Location Always Usage Description
Privacy - Location When In Use Usage Description
The ´locationManager´ is defined in class property:
let locationManager = CLLocationManager()
I have searched a lot and did not find any solution. Do you have any suggestions? Thank you!

You need
let locationManager = CLLocationManager()
locationManager.delegate = self
class MYVC:UIViewController,CLLocationManagerDelegate { --- }
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) { --- }
This locationManager.requestLocation() returns void not the current location , it starts the query for current location then call didUpdateLocations when gets it so you may print(locations.last) , also you may only need
Privacy - Location Always and When In Use Usage Description
as it includes the 2 other permissions

Related

DidUpdateLocation not storing location, userLoc always nil

I am trying to simply get the user's current device location and store it in a global variable called userLoc. I have this code to call didUpdateLocation:
self.locationManager.requestLocation()
print("aaa ", self.userLoc)
and this to set the userLoc to the current location:
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
self.userLoc = location
}
}
userLoc is defined like this:
var userLoc: CLLocation?
but when I run the app and try to print userLoc, it ALWAYS prints:
aaa nil
The Privacy - Location When In Use Usage Description is set in the Info.plist. I honestly dont know what else to try. I've been banging my head against the wall for a while trying to fix this. Any help you could give would be very much appreciate. Thank you.
This is what I do to get user location within my view controller class. I think you are missing locationManager.startUpdatingLocation():
var currentLocation: CLLocationCoordinate2D!
var locationManager: CLLocationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
currentLocation = locationManager.location!.coordinate

CLLocationManager is slow getting location, Swift

Im creating this app, and it needs to get the users location - its all working properly, the thing is, that the time from accepting the use of location services, to getting the actual location takes like 5 seconds - is this normal?
I've used other apps, where it goes much faster..
Here's what my code looks like:
override func viewDidLoad() {
super.viewDidLoad()
// Ask for Location-Authorisation from the User.
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.requestLocation()
}
mapView.delegate = self
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue: CLLocationCoordinate2D = manager.location!.coordinate
let initialLocation = CLLocation(latitude: locValue.latitude, longitude: locValue.longitude)
self.centerMapOnLocation(initialLocation)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("could not get location")
}
But the time from the application gets the location to put into the centerMapOnLocation-function, seems just to be quite long. What is to be expected, when getting a users location? I'm testing on a wifi connection, so I know its not because the internet is slow, or its a bad connection...
Anyone have an idea? :)
Best regards!
Try setting the accuracy and use locationManager.startUpdatingLocation(). I do that, and get answer within a second (on the device).
From the documentation of requestLocation():
This method returns immediately. Calling it causes the location manager to obtain a location fix (which may take several seconds) and call the delegate’s locationManager(_:didUpdateLocations:) method with the result.
Source
So basically, everything is fine with your code, it's just how the framework is built.
When initializing your location manager, add startUpdatingLocation():
let manager = CLLocationManager()
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.requestLocation()
manager.startUpdatingLocation()
Without startUpdatingLocation() geo-location takes about 5 seconds, with it, the request executes nearly immediately.
If you don't want to delay the app's launch for the location manager, consider deploying two location managers (in the app delegate), tasking one with generating a location quickly and the other with generating a location accurately:
fastLoc.delegate = self
fastLoc.desiredAccuracy = kCLLocationAccuracyThreeKilometers
fastLoc.requestWhenInUseAuthorization()
fastLoc.startUpdatingLocation()
bestLoc.delegate = self
bestLoc.desiredAccuracy = kCLLocationAccuracyBest
bestLoc.requestWhenInUseAuthorization()
bestLoc.requestLocation()
The combination of 3 km accuracy with startUpdatingLocation() should return a location almost instantly, almost always before the root view controller is even ready to go. bestLoc manager is likely to return a location well after the user has launched the app but it will be very accurate.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
switch manager {
case fastLoc:
fastLoc.stopUpdatingLocation()
deviceLocation = locations.last! // set property with fast loc
case bestLoc:
deviceLocation = locations.last! // overwrite property with best loc
default:
break
}
}

How do I display the altitude of the user in swift?

I'm trying to build an app that displays the altitude of the user, but xCode says that CLLocation doesn't have member 'altitude'. The code I'm using is
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { self.Altitude.text = String(locations.altitude)}
Xcode does not say "CLLocation" has no member 'altitude'" but "[CLLocation] has no member 'altitude'".
locations is an array of CLLocation objects and (as it is an array) does not have a property named altitude.
What you need to do is extract one value from the array and use that to access the altitude.
You probably want to do something like this:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let altitude = locations.last?.altitude else { return }
self.Altitude.text = String(altitude)
}
Since this is a user facing string you should format it properly using a LengthFormatter.
A small style note: variable names (like self.Altitude should be lowercased, only types are PascalCase).
You can get Altitude from reverse geocoding in swift for this you can use locationManager and locationManager didUpdateLocations method.
Step 1: Add below Code in ViewdidLoad method:-
let locationManager = CLLocationManager()
locationManager.headingFilter = 1
locationManager.delegate = self
locationManager.startUpdatingHeading()
Step 2: Use didUpdateLocations Method:-
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let altitude = locations.last?.altitude else { return }
}

Trouble getting one-time user location in Swift

I am trying to get the user's location at the time of a button press, however I am having trouble setting up the location code. I've been looking between various answers on Stackoverflow but I can't get anything to work for me.
class MyViewController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedAlways || status == .AuthorizedWhenInUse {
let latitude = self.locationManager.location?.coordinate.latitude
let longitude = self.locationManager.location?.coordinate.longitude
print("coordinates:")
print(latitude)
print(longitude)
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locationValue : CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locationValue.latitude) \(locationValue.longitude)")
}
However I just get nils from the prints in didChangeAuthorizationStatus and nothing ever prints from didUpdateLocations. Im also really confused about where to put startUpdatingLocation(). Some answers place it directly in viewDidLoad as I have here, others place it in didChangeAuthorizationStatus, and I saw another place it inside an if CLLocationManager.locationServicesEnabled() in didLoad. What is the correct way to do this? And also what have I done wrong that I'm not getting any values printing? I'm running on the emulator, have location turned on and allowed permissions in the pop-up, and have the emulator set to a lat/long custom location, and I have added the values in pList.
edit: even tried copy/pasting the code from this to get user's location only once but it returns (kCLErrorDomain error 0.). I added a 'requestWhenInUseAuthorization()` to their code but it still fails.
get nils from the prints in didChangeAuthorizationStatus
Because we don't have any locations yet. That's the wrong place to ask for that information. All that happened is that we are now authorized.
nothing ever prints from didUpdateLocations
Because you're running on the simulator, perhaps. Try running on a device.
And, if your goal is just to get the location and stop, don't use startUpdatingLocation; call requestLocation. That's what it's for.

CLLocation manager delegate not called despite Plist keys

I'm writing an app in swift and need to access the user's location. I added the CLLocationManagerDelegate at the top of the class and set the delegate to self. I also added these keys in the plist because I read in iOS 8 or later it's necessary...
NSLocationAlwaysUsageDescription --- I need Location
NSLocationWhenInUseUsageDescription --- I need Location
privacy - location usage description --- I need Location
It calls the first method below with no problem (called from view did load), where the delegate and request always authorization are, but then it fails to call the second(delegate) method.
func determineCurrentUserLocation() {
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
location = (locations[0] as? CLLocation)!
let long = location.coordinate.longitude
let lat = location.coordinate.latitude
longString = String(format: "#%", long)
latString = String(format: "#%", lat)
println("\(long, lat)")
}
Is this simply because I'm on the simulator? Would it work on a real device? Is there any way to get it to work on a simulator? Thank you!