i'm trying to pass my latitude and longitude to my url params but is returning Nil, but when i print within the delegate it returns the longitude and latitude and i can't seem to find the issue, i've tried many different ways and nothing seems to work
this are the variable where i store my latitude and longitude
var lat: Double!
var long: Double!
this is my delegate
func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]){
currentLocation = manager.location!.coordinate
let locValue:CLLocationCoordinate2D = currentLocation!
self.long = locValue.longitude
self.lat = locValue.latitude
print(lat)
print(long)
}
and here pass them to variables i'm using in my URL parameters but they return nil and i don't understand why
let userLat = String(describing: lat)
let userLong = String(describing: long)
Thank You
Try something like:
Swift 3
func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]){
if let last = locations.last {
sendLocation(last.coordinate)
}
}
func sendLocation(_ coordinate: CLLocationCoordinate2D) {
let userLat = NSString(format: "%f", coordinate.latitude) as String
let userLong = NSString(format: "%f", coordinate.longitude) as String
// Run API Call....
}
I think the Joseph K's answer is not correct. It rounds off the values of the latitude and longitude. It will be something like the code below.
let coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(exactly: 35.6535425)!, longitude: CLLocationDegrees(exactly: 139.7047917)!)
let latitude = coordinate.latitude // 35.6535425
let longitude = coordinate.longitude // 139.7047917
let latitudeString = NSString(format: "%f", latitude) as String // "35.653543"
let longitudeString = NSString(format: "%f", longitude) as String // "139.704792"
So the correct and simpler code is:
Swift 3
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let coordinate = locations.last?.coordinate else { return }
let latitude = "\(coordinate.latitude)"
let longitude = "\(coordinate.longitude)"
// Do whatever you want to make a URL.
}
Related
Currently the user location is logged each time he visits the home screen. It needs to also update when the user is on the move so that the location stays current.
Here I set the location upon login
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
print("locations = \(locValue.latitude) \(locValue.longitude)")
latestLocation = ["latitude" : locValue.latitude, "longitude" : locValue.longitude]
let lat = locValue.latitude
let lon = locValue.longitude
dict = CLLocation(latitude: lat, longitude: lon)
print("dict", dict)
if let locationDictionary = latestLocation {
databaseRef.child("people").child(uid).child("Coordinates").setValue(locationDictionary)
}
}
Now I just nee it to always setValue when user moves materially.
You can look into startMonitoringSignificantLocationChanges() method and don't for get to call startUpdatingLocation
I try to display the distance between a post creator and the current user within a cell.
My error now is
Cannot convert value of type 'String?' to expected argument type 'CLLocationDegrees' (aka 'Double')
in the following code:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let lastLocation = locations.last {
let geoCoder = CLGeocoder()
let myLocation = CLLocation(latitude: lastLocation.coordinate.latitude, longitude: lastLocation.coordinate.longitude)
/*Here the error*/ let myBuddysLocation = CLLocation(latitude: job!.distance, longitude: job!.distance)
let distance = myLocation.distance(from: myBuddysLocation) / 1000
print(String(format: "The distance to my buddy is %.01fkm", distance))
}
}
This is my JobClass:
class Job {
var distance: String?
let ref: DatabaseReference!
init(distance: String? = nil) {
self.distance = distance
ref = Database.database().reference().child("jobs").childByAutoId()
}
init(snapshot: DataSnapshot){
ref = snapshot.ref
if let value = snapshot.value as? [String : Any] {
distance = value["distance"] as? String
}
}
func save() {
let newPostKey = ref.key
let postDictionary = [
"distance" : self.distance!
] as [String : Any]
self.ref.setValue(postDictionary)
}
}
I hope someone knows how to solve it, if you wan't I can add more code if it helps // I'm new to coding
The error is self-explanatory: You are trying to set a String? instead of a CLLocationDegrees, but you can even use a Double type.
There are several ways to fix this:
1) You can change your class definition as it follows:
class Job {
// Change distance to Double and set a default value instead of optional
var distance: Double = 0.0
let ref: DatabaseReference!
// Change the init
init(distance: Double = 0.0) {
self.distance = distance
ref = Database.database().reference().child("jobs").childByAutoId()
}
//You have to change all your distance to Double
init(snapshot: DataSnapshot){
ref = snapshot.ref
if let value = snapshot.value as? [String : Any] {
// So change this cast
distance = value["distance"] as Double
}
}
}
2) You can try a cast from String? to Double, but I don't recommend this.
Anyway, here it is how you can do it:
if let dist = Double(job!.distance){
let myBuddysLocation = CLLocation(latitude: dist, longitude: dist) -> Error Appears in this Line
let distance = myLocation.distance(from: myBuddysLocation) / 1000
print(String(format: "The distance to my buddy is %.01fkm", distance))
}
Actually in your function the only problem are there you passing the string value in place of double you need to change like this.
let myBuddysLocation = CLLocation(latitude: Double.init(job!.distance) ?? 0.0, longitude: Double.init(job!.distance) ?? 0.0)
You need to change your function like this
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let lastLocation = locations.last {
let geoCoder = CLGeocoder()
let myLocation = CLLocation(latitude: lastLocation.coordinate.latitude, longitude: lastLocation.coordinate.longitude)
let myBuddysLocation = CLLocation(latitude: Double.init(job!.distance) ?? 0.0, longitude: Double.init(job!.distance) ?? 0.0)
let distance = myLocation.distance(from: myBuddysLocation) / 1000
print(String(format: "The distance to my buddy is %.01fkm", distance))
}
}
It's normal because distance should be Double value. Changing it to: var distance: Double? should correct it.
Or parse the value to Double let myBuddysLocation = CLLocation(latitude: Double(distance)!, longitude: Double(distance)!)
I recommend you to avoid using ! because it could generate a fatal error if the string isn't a number, you can guard the value with guard or if let like this example:
if let latitude = Double(distance) {
let myBuddysLocation = CLLocation(latitude: latitude, longitude: latitude)
}
I have experience crash of the app when using it in US. In all other countries same code is working. The crash is happening on line:
let latitude = String(format: "%.7f", currentLocation.coordinate.latitude)
I really can't see what is the problem, specially cos is related to US and not to other counties. Any help will be very very much appreciate.
My UserLocation.swift looks like this:
import UIKit
import MapKit
public class GPSLocation {
static let sharedInstance = GPSLocation()
//MARK: Public variables
public var intermediateLatitude: String?
public var intermediateLongitude: String?
public var intermediateCountry: String?
public var intermediateCity: String?
public var intermediateTimeZone: String?
//MARK: Get Longitude, Country Code and City name
func getGPSLocation(completition: #escaping () -> Void) {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locManager = manager
var currentLocation: CLLocation!
locManager.desiredAccuracy = kCLLocationAccuracyBest
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse || CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {
currentLocation = locManager.location
if currentLocation != nil {
// Get longitude & latitude
let latitude = String(format: "%.7f", currentLocation.coordinate.latitude)
let longitude = String(format: "%.7f", currentLocation.coordinate.longitude)
self.intermediateLatitude = latitude
self.intermediateLongitude = longitude
// debugPrint("Latitude:",latitude)
// debugPrint("Longitude:",longitude)
// Get local time zone GMT
let localTimeZoneAbbreviation = TimeZone.current.abbreviation() ?? "" // "GMT-2"
let indexStartOfText = localTimeZoneAbbreviation.index(localTimeZoneAbbreviation.startIndex, offsetBy: 3) // 3
let timeZone = localTimeZoneAbbreviation.substring(from: indexStartOfText) // "-2"
self.intermediateTimeZone = timeZone
// debugPrint("GMT:",timeZone)
// Get Country code and City
let location = CLLocation(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude)
fetchCountryAndCity(location: location) { countryCode, city in
self.intermediateCountry = countryCode
self.intermediateCity = city
// debugPrint("Country code:",countryCode)
// debugPrint("City:",city)
completition()
}
} else {
// Location is NIL
}
}
}
locManager.delegate = self // and conform protocol
locationManager.startUpdatingLocation()
}
//MARK: Find countryCode & City name from longitude & latitude
func fetchCountryAndCity(location: CLLocation, completion: #escaping (String, String) -> ()) {
CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
if let error = error {
debugPrint(error)
} else if let countryCode = placemarks?.first?.isoCountryCode,
let city = placemarks?.first?.locality {
completion(countryCode, city)
}
}
}
}
You need to check location in delegate method
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation() // if you dont want continuously update
currentLocation = manager.location
let location = CLLocation(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude)
fetchCountryAndCity(location: location) { countryCode, city in
self.intermediateCountry = countryCode
self.intermediateCity = city
// debugPrint("Country code:",countryCode)
// debugPrint("City:",city)
completition()
}
}
And set delegate
locManager.delegate = self // and conform protocol
locationManager.startUpdatingLocation()
I want to calculate the distance from my location to another.
I found this line of code:
let distanceInMeters = location1.distanceFromLocation(location2)
But my problem is that I don't know how to take it from latitude and longitude.
So, you just need to create 2 CLLocation objects from your lat and long and then just call the line of code that you found.
let location1 = CLLocation(latitude: 20.0, longitude: 20.0)
let location2 = CLLocation(latitude: 30.0, longitude: 30.0)
let distanceInMeters = location1.distanceFromLocation(location2)
Also, this will return you distance in meters, not in km.
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var userLocation:CLLocation = locations[0] as! CLLocation
let long = userLocation.coordinate.longitude;
let lat = userLocation.coordinate.latitude;
// use it for your code
}
You can try this function, I use it in my code
I am new to Swift and I need to calculate the nearest places around my current location. Would you advice me which function should I use to calculate the distance between my location and the nearest around me. I have to display the distance and the places in the app,so that the user can choose which one fits best for him.I think I should use latitude and longitude coordinates which can be compared with mine. I also found out that I have to use distanceFromLocation , but I do not know how and I would be glad if someone provide me with an example which I can use for my code.
My code so far is:
class ViewThree: UIViewController, CLLocationManagerDelegate{
#IBOutlet weak var SegmentControl: UISegmentedControl!
#IBOutlet weak var Mapview: MKMapView!
var manager = CLLocationManager()
var receiveImeNaSladkarnica: String = ""
var KordaA: String = ""
var KordaB: String = ""
var PodImeNaObekt: String = ""
override func viewDidLoad() {
super.viewDidLoad()
let pinLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake((KordaA as NSString).doubleValue,(KordaB as NSString).doubleValue)
let objectAnn = MKPointAnnotation()
objectAnn.coordinate = pinLocation
objectAnn.title = receiveImeNaSladkarnica
objectAnn.subtitle = PodImeNaObekt
self.Mapview.addAnnotation(objectAnn)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func Directions(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string: "http://maps.apple.com/maps?daddr=\((KordaA as NSString).doubleValue),\((KordaB as NSString).doubleValue))")!)
}
#IBAction func MapType(sender: AnyObject) {
if (SegmentControl.selectedSegmentIndex == 0){
Mapview.mapType = MKMapType.Standard
}
if (SegmentControl.selectedSegmentIndex == 1){
Mapview.mapType = MKMapType.Satellite
}
}
#IBAction func LocateMe(sender: AnyObject) {
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
Mapview.showsUserLocation = true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userlocation: CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userlocation.coordinate.latitude, longitude: userlocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.5, 0.5)
let region = MKCoordinateRegion(center: location, span: span)
Mapview.setRegion(region, animated: true )
}
I had the same scenario with an other app.
Within the CLLocation object, there is an instance function:
func distanceFromLocation(location: CLLocation) -> CLLocationDistance
//Get your two locations that you want to calculate the distance from:
let userLocation: CLLocation = ...
let locationToCompare: CLLocation = ...
// Returned value is in meters
let distanceMeters = userLocation.distanceFromLocation(locationToCompare)
// If you want to round it to kilometers
let distanceKilometers = distanceMeters / 1000.00
// Display it in kilometers
let roundedDistanceKilometers = String(Double(round(100 * distanceKilometers) / 100)) + " km"
UPDATED
For your use case
let locations = ... // All locations you want to compare
for location in locations {
let distanceMeters = userLocation.distanceFromLocation(location)
if distanceMeters > 5000 { // Some distance filter
// Don't display this location
} else {
// Display this location
}
}
MY CODE:
IMPROVED
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userlocation:CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userlocation.coordinate.latitude, longitude: userlocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.5, 0.5)
let region = MKCoordinateRegion(center: location, span: span)
Mapview.setRegion(region, animated: true)
let locationStrings = ["42.6977,23.3219","43.6977,24.3219"]
// This array must be an array that contains CLLocation objects
var locations: [CLLocation] = []
// We must retrieve the latitude and longitude from locationStrings array to convert them into CLLocation objects
for locationString in locationStrings {
let location = CLLocation(latitude: <latitude_value>, longitude: <latitude_value>)
locations.append(location)
}
// Then you will be able to enumerate through the array
for location in locations {
let distanceMeters = userLocation.distanceFromLocation(location)
if distanceMeters > 5000 { // Some distance filter
// Don't display this location
} else {
// Display this location
}
}
You can use distanceFromLocation method to get distance
let distance = userlocation.distanceFromLocation(YourPinInMap)
locA = [[CLLocation alloc] initWithLatitude:[[[NSUserDefaults standardUserDefaults]valueForKey:#"startLat"]floatValue] longitude:[[[NSUserDefaults standardUserDefaults]valueForKey:#"startlong"]floatValue]];
locB = [[CLLocation alloc] initWithLatitude:[[[NSUserDefaults standardUserDefaults]valueForKey:#"destLat"]floatValue] longitude:[[[NSUserDefaults standardUserDefaults]valueForKey:#"destLong"]floatValue]];
distance = [locA distanceFromLocation:locB];
where locA and locB are CLLocation type pass the lat long over there