Swift - How to get latitude and longitude value outside function LocationManager() - swift

i am working with Firebase Db, and i want to save lat,long value of device on Firebase. I had two value from locationManager()
This is my function locationManager()
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let lastLocation: CLLocation = locations[locations.count - 1]
let lat = String(format: "%.6f", lastLocation.coordinate.latitude)
let long = String(format: "%.6f", lastLocation.coordinate.longitude)
}
Next, i try TO save lat,long on Firebase:
ref = FIRDatabase.database().reference()
ref.setValue(lat)
Error: "Use of Unresolved Identifier".
How to get latitude and longitude value outside function LocationManager().

You can declare CLLocationManagerDelegate right where of your class definition.
class YourClass {
private var currentCoordinate: CLLocationCoordinate2D?
}
And in your location delegate method you assign the current value
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
currentCoordinate = manager.location.coordinate
}

Related

Could not get current Location from CLLocationManager

class LocationManager: NSObject, CLLocationManagerDelegate {
private var onLocation: ((CLLocationCoordinate2D) -> Void)?
private let manager: CLLocationManager
override init() {
manager = CLLocationManager()
super.init()
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.delegate = self
manager.startUpdatingLocation()
}
public func getLocation(_ onLocation: ((CLLocationCoordinate2D) -> Void)?) {
self.onLocation = onLocation
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(#function, locations)
guard let currentCoordinate = manager.location?.coordinate else {return}
onLocation?(currentCoordinate)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(#function, error)
}
}
this code is not calling didUpdateLocation or didFailWithError. can anyone tell me what could be the problem here?
LocationManager().getLocation { coordinate in
print(#function, coordinate)
}
this is how i am calling it.
You need to retain the let manager = CLLocationManager() in your class as a property. Otherwise, it will be deallocated at the end of that function and hence none of its delegate methods will be called at all.
UPDATED
Another issue is the following code where you call getLocation. You need to retain LocationManager() in your client class otherwise the LocationManager will be deallocated at the end of that function.
private let locationManager = LocationManager()
locationManager.getLocation { coordinate in
print(#function, coordinate)
}

I want to take out the coordinates acquired in the delegate

I wrote a program that uses LocationManagerDelegate to display coordinates in the debug area whenever the current location changes. Got an error when retrieving coordinates
Can not use instance member 'locationManager' within property initializer; property initializers run before 'self' is available
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setUpLocationManager()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setUpLocationManager() {
locationManager = CLLocationManager()
guard let locationManager = locationManager else {return}
locationManager.requestWhenInUseAuthorization()
let status = CLLocationManager.authorizationStatus()
if status == .authorizedWhenInUse {
locationManager.delegate = self
locationManager.distanceFilter = 10
locationManager.startUpdatingLocation()
printLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) ->Optional<Any> {
let location = locations.first
let latitude = location?.coordinate.latitude
let longitude = location?.coordinate.longitude
let latlong = [latitude, longitude]
return latlong
}
let myLocation = locationManager()
func printLocation() {
print("test\(myLocation)")
}
}
test (Function)
is output
let myLocation = locationManager ()
When you change to
let myLocation = locationManager
Your code contains a few mistakes.
The error occurs because you cannot execute the affected line on the top level of the class.
First of all you must not change signatures of delegate methods. This custom delegate method
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) ->Optional<Any> { ...
will never be called.
And apart from that why do you declare the return type as Any? although it's supposed to be [CLLocationCoordinate2D]?
Create the location manager immediately, replace
var locationManager: CLLocationManager!
with
let locationManager = CLLocationManager()
In setUpLocationManager() delete the lines
locationManager = CLLocationManager()
guard let locationManager = locationManager else {return} // this line is completely pointless anyway
printLocation()
The delegate method didUpdateLocations is called periodically and asynchronously. Print the result inside the method
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else { return }
let latitude = location.coordinate.latitude
let longitude = location.coordinate.longitude
let latlong = [latitude, longitude]
print("test", latlong)
}
Delete
let myLocation = locationManager()
func printLocation() {
print("test\(myLocation)")
}

Add Coordinates (from UIViewController) to Constants File

I pulled the coordinates from the user in my main view controller like this:
import CoreLocation
private let locationManager = CLLocationManager()
func findCurrentLocation() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
//locationManager.startUpdatingHeading
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
I then have this URL in a separate file (my constants file)
let NEAREST_CITY_URL = BASE_URL + "nearest_city?lat={{LATITUDE}}&lon={{LONGITUDE}}&key=" + API_KEY
I need to get the latitude and longitude from the view controller into that URL. How would I pass it there?
I assume it needs to look something like this, but I can't figure out how to compile it without errors.
let NEAREST_CITY_URL = BASE_URL + "nearest_city?lat=\(MainVC.locationManager.locValue.latitude)&lon=\(MainVC.locationManager.locValue.longitude)&key=" + API_KEY
MainVC needs to set the data into your constants file, as a global variable (since you seem to desire using globals... eek). Then you can offer a NEAREST_CITY_URL that computes a string using that data.
In your constants file:
var userLoc : CLLocationCoordinate2D?
let NEAREST_CITY_URL = BASE_URL + "nearest_city?lat=\(userLoc.latitude ?? 0.0)&lon=\(userLoc.longitude ?? 0.0)&key=" + API_KEY
In your view controller:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
print("locations = \(locValue.latitude) \(locValue.longitude)")
userLoc = locValue
}
Now it's really bad to have a global constants file like you're doing... at the very least, place all your constants into a singleton class named Constants. But I'm just here to directly answer your question, so...

Swift request geolocation from non-view

I'm trying to get geolocation data in an arbitrary class. I'm very new to Swift, so I have no idea why this isn't working?
Any pointers?
import Foundation
import UIKit
import CoreLocation
class GeolocationPlugin:NSObject, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
var lat: Double = 0
var long: Double = 0
func getLocation() {
print("Getting location")
// For use in foreground
self.locationManager = CLLocationManager()
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
// locationManager.startMonitoringSignificantLocationChanges()
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError) {
print("Error while updating location " + error.localizedDescription)
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
self.locationManager.requestLocation()
print("gets here")
}
}
I currently see Getting location and then an error:
2017-03-26 15:42:32.634 IonicRunner[42304:5668243] *** Assertion failure in -[CLLocationManager requestLocation], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreLocationFramework_Sim/CoreLocation-2100.0.34/Framework/CoreLocation/CLLocationManager.m:865
2017-03-26 15:42:32.638 IonicRunner[42304:5668243] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Delegate must respond to locationManager:didUpdateLocations:'
The solution wound up being to move the methods out of getLocation(), to properly activate a location in the simulator, and to move where this class was initiated from, so it wasn't immediately released as soon as getLocation() completes.
import Foundation
import UIKit
import CoreLocation
class GeolocationPlugin:NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var lat: Double = 0
var long: Double = 0
var cb: ((Double, Double) -> Void)? = nil
func getLocation(callback: #escaping (Double, Double) -> Void) {
print("Getting location")
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestLocation()
self.cb = callback
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: NSError) {
print("Error while updating location " + error.localizedDescription)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
//print("locations = \(locValue.latitude) \(locValue.longitude)")
if( self.cb != nil) {
self.cb!(locValue.latitude, locValue.longitude)
}
}
}

how to pass longitude and latitude from CLLocationManager to use globally swift

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var locValue:CLLocationCoordinate2D = manager.location.coordinate
println("locations = \(locValue.latitude) \(locValue.longitude)")
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)->Void in
if (error != nil) {
println("Error: " + error.localizedDescription)
return
}
if placemarks.count > 0 {
let pm = placemarks[0] as CLPlacemark
self.locationManager.stopUpdatingLocation()
//self.dismissViewControllerAnimated(true, completion: nil)
self.displayLocationInfo(pm)
} else {
println("Error with the data.")
}
})
}
Currently I'm able to get the current location with coordinate and I'm able to print it. But how can I send the value in the function to web service? I found that the variable is not accessible outside of the function. Can anyone help? Thanks a lot!
If you want to access your location variable outside the CLLocationManagerDelegate method you should declare it right where your class definition starts:
class MyClass {
private var currentCoordinate: CLLocationCoordinate2D?
}
Then in your location delegate method you assign the current value:
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
currentCoordinate = manager.location.coordinate
}