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 }
}
Related
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
I want to get a new location when my app is in the background or killed state. I searched a lot and found out the method in the Apple doc. startMonitoringSignificantLocationChanges() for updating location when app is in background or killed state. But when I try this method didn't getting the location in the killed state.
Here is my code :
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.startMonitoringSignificantLocationChanges()
}
//MARK: LOCATION MANAGER:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let long :CLLocationDegrees = manager.location?.coordinate.longitude ?? 00.00000
let lat :CLLocationDegrees = manager.location?.coordinate.latitude ?? 00.00000
print(lat)
print(long)
let location = LocationTracking()
location.latitude = lat
location.longitude = long
try! realm.write {
realm.add(location, update: false)
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error",error.localizedDescription)
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.denied) {
print("Location access denied")
}
}
After setting Background Modes Capabiity on, you can use startMonitoringSignificantLocationChanges() instead of startUpdatingLocations(). This method notifies you of changes in 500 meters.
And you can read this quote by public api.
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati
Let me explain myself. I have created a Map where I show some locations (pins) and the user location. When I run the App, it opens and zooms in (span), then I want to move through the map, but the App "drags" the view back to the user location (it even zooms in back to normal state). My question is, how can I stop my App from doing that over and over again? because it is kind of annoying. Thanks in advance.
The function I used for this Span process was the following...
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span: MKCoordinateSpan = MKCoordinateSpanMake(1.0, 1.0)
let ubicacionUsuario: CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region: MKCoordinateRegion = MKCoordinateRegionMake(ubicacionUsuario, span)
mapView.setRegion(region, animated: true)
self.mapView.showsUserLocation = true
}
Inside of your didUpdateLocations function, you can create a counter. Essentially, what the counter would do is update and refresh the user's location on the map for a specific number of iterations. After that, you can use the .stopUpdatingLocation method of the CLLocationManager. So, for your case, you would have something like below:
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
// Top level class stuff, create CLLocationManager Instance
var manager = CLLocationManager()
// set initial value of counter to 0
var updateCount = 0
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//If the location has updated less than 3 times, continue to update the location
if updateCount < 3 {
let region: MKCoordinateRegion = MKCoordinateRegionMake(ubicacionUsuario, span)
mapView.setRegion(region, animated: true)
updateCount += 1
} else {
// Once the update has occurred a satisfactory number of times, prevent the update from automaitcally occuring again
manager.stopUpdatingLocation()
}
}
}
For some reason I cannot seem to get the users location. I bought the iOS 9 CookBook and coped their code exactly
Here is the ViewController:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
lazy var locationManager: CLLocationManager = {
let m = CLLocationManager()
m.delegate = self
m.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
return m
}()
func locationManager(manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
//TODO: now you have access to the location. do your work
}
func locationManager(manager: CLLocationManager,
didFailWithError error: NSError) {
//TODO: handle the error
}
func locationManager(manager: CLLocationManager,
didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if case .AuthorizedWhenInUse = status{
manager.requestLocation()
} else {
//TODO: we didn't get access, handle this
print("No Access Granted")
}
}
#IBAction func requestLocation() {
locationManager.requestWhenInUseAuthorization()
}
}
The output in the console is:
No Access Granted
Any ideas what is going on? I have tested this on both the simulator and the device
Edit: I have added a button to the storyboard and licked that to the IBAction accordingly.
Have you added the NSLocationWhenInUseUsageDescription key to your plist? - The value should be a string describing why you want to use the users location.
<key>NSLocationWhenInUseUsageDescription</key>
<string>Required to provide information about your location.</string>
If its all working correctly the didUpdateLocations delegate method should return an array of locations, you can print these out like so...
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for loc in locations {
print(loc)
}
}
If you want to continually monitor the location you can call manager.startUpdatingLocation() instead of manager.requestLocation()
I would like to call a method but it requires coordinates that have not been stored in variables yet.
So far I have:
1) acquired current location
2) Think I store them?
What I want to do:
1) Call method After these variables are stored so the program can run
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var clLatitude : CLLocationDegrees!
var clLongitude: CLLocationDegrees!
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location:CLLocationCoordinate2D = manager.location!.coordinate
//Test printing coordinates to screen
print("locations = \(location.self.clLatitude) \(location.self.clLongitude)")
//place where I think I store the variables?
self.clLatitude = location.latitude
self.clLongitude = location.longitude
}
func methodToBeCalled(){
//to be called after variables are stored.
}
I believe I have covered everything regarding my problem
i think you just need to call the method at the end of locationManager(manager: didUpdateLocations:)
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location:CLLocationCoordinate2D = manager.location!.coordinate
//Test printing coordinates to screen
print("locations = \(location.self.clLatitude) \(location.self.clLongitude)")
//place where I think I store the variables?
self.clLatitude = location.latitude
self.clLongitude = location.longitude
// call method
methodToBeCalled()
}
func methodToBeCalled(){
//to be called after variables are stored.
}