i'm a beginner in developing an i'm adding a google map on a view of my application, following a tutorial i used this code
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: zoomlevel)
let marker = GMSMarker()
marker.title = "My Position"
marker.map = mapView
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
} else {
mapView.animate(to: camera)
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
print("Location access was restricted.")
case .denied:
print("User denied access to location.")
mapView.isHidden = false
case .notDetermined:
print("Location status not determined.")
case .authorizedAlways: fallthrough
case .authorizedWhenInUse:
print("Location status is OK.")
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
to find the user location, now i would like to see on the map the places (google places) that are on a X distance from the user position, how can i do it? i searched on the google places doc but not find a valid answer
Add another marker onTap on mapView and make it draggable and use CLLocationDistance to measure distance between 2 locations.
let distanceInMeters = self.locationManager.location?.distance(from: newMarkerLocation!)
Related
I am using location.requestLocation in swift 5 for my ios app. But its taking way too long time. around 10 seconds. searching for solutions online, they are saying use startUpdatingLocation instead..but problem is I only want it once... not continuous update. I am also not interested in it being accurate.I can have it wrong by some margin.
Because all I want is just zoom to my google map position, and sort stuff by distance using user location. Location can be wrong up to 3 - 4 Kilometers I have no problem.
override func viewDidLoad() {
super.viewDidLoad()
//mapView.showsUserLocation = false
locationManager.delegate = self
print(locationManager.distanceFilter)
switch CLLocationManager.authorizationStatus() {
case CLAuthorizationStatus.notDetermined, .restricted, .denied:
locationManager.requestWhenInUseAuthorization()
case CLAuthorizationStatus.authorizedWhenInUse, .authorizedAlways:
requestLocation()
#unknown default: break
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print("\nStart of locationManager(didChangeAuthorization)")
let authStatus = CLLocationManager.authorizationStatus()
if authStatus == CLAuthorizationStatus.authorizedWhenInUse
|| authStatus == CLAuthorizationStatus.authorizedAlways {
requestLocation()
}
print("\nEnd of locationManager(didChangeAuthorization)")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("\nStart of locationManager(didUpdateLocations)")
zoomInLocation(locations.last!)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
if let err = error as? CLError, err.code == .denied {
manager.stopUpdatingLocation()
return
}
print("\nlocationManager(): \(error.localizedDescription)")
}
private func requestLocation() {
print("\requestLocation() called")
// check if the location service is availalbe on that device
if !CLLocationManager.locationServicesEnabled() {
return
}
locationManager.requestLocation()
}
private func zoomInLocation(_ location: CLLocation) {
loca2 = location
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: 6.0)
(view1 as! GMSMapView).animate(to: camera)
print("\nzoomInUserLocation(): mapView[latitude]=\(location.coordinate.latitude), locationManager[latitude]=\(String(describing: location.coordinate.latitude))")
let coordinateSpan = MKCoordinateSpan(latitudeDelta: 20, longitudeDelta: 20)
_ = MKCoordinateRegion(center: location.coordinate, span: coordinateSpan)
// mapView.centerCoordinate = location.coordinate
//mapView.setRegion(coordinateRegion, animated: true)
if(i1 != 0){
self.sortByDistance()
}
}
This is how I init the map - GMSMapView
class ViewController: UIViewController {
var map = GMSMapView()
override func viewDidLoad() {
super.viewDidLoad()
setupGoogleView()
}
private func setupGoogleView() {
guard let coordinates = getUserLocation() else { return }
let camera = GMSCameraPosition.camera(withLatitude: coordinates.latitude, longitude: coordinates.longitude, zoom: 16.0)
self.map = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
map.settings.tiltGestures = false
map.mapType = .satellite
map.delegate = self
map.frame = view.frame
self.view.addSubview(map)
}
}
The problem comes when I call this function from somewhere else in the file
private func animateTo(location: CLLocationCoordinate2D) {
DispatchQueue.main.async {
let cameraPosition = GMSCameraPosition(target: location, zoom: 20)
self.map.animate(toLocation: location)
self.map.animate(to: cameraPosition)
}
}
I am trying to relocate the camera to some coordinates, but nothing happens.
I have tried every solution on stackoverflow and google.
I have lat and lng in the location - checked. The function is called - checked.
I have also tried to self.view.layoutSubviews(), self.view.layoutIfNeeded(), and also for map
try to use CLLocationManagerDelegate
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
print("Location access was restricted.")
case .denied:
print("User denied access to location.")
// Display the map using the default location.
mapView.isHidden = false
case .notDetermined:
print("Location status not determined.")
case .authorizedAlways: fallthrough
case .authorizedWhenInUse:
print("Location status is OK.")
getFilialList()
#unknown default:
fatalError()
}
}
then
// Handle incoming location events.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: 12)
DispatchQueue.main.async {
self.mapView.animate(to: camera)
self.locationManager.stopUpdatingLocation()
}
}
I manage to solve the issue with this:
self.view.subviews.forEach { (view) in
if let mapView = view as? GMSMapView {
// do update on mapView here
}
}
I have been looking at the google documentation to get the current location, but i am struggling to specify the location in the ViewDidLoad, as you can see i have set the Location fixed to Syndey Australia. In the google doc documentation when specifying the current location, they are using the "default location.coordinate" , i cannot access defaultLocation.coordinate in my code .
here is a link to the documenation : https://developers.google.com/maps/documentation/ios-sdk/current-place-tutorial
this is the code inside the viewDidLoad
GMSServices.provideAPIKey("AIzaSyARsPfNs54hrUAC4yKtHeu2jXfGjeA0b-E")
GMSPlacesClient.provideAPIKey("AIzaSyARsPfNs54hrUAC4yKtHeu2jXfGjeA0b-E ")
let camera = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 6.0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
// creating the marker //
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: -33.86, longitude: 151.20)
marker.title = "Sydney"
marker.snippet = "Australia"
marker.map = mapView
This is my extenstion code
extension MapsViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location : CLLocation = locations.last!
print("Location:\(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: zoomLevel)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
}
else {
mapView.animate(to: camera)
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
// display the map the default location
mapView.isHidden = false
case .denied :
print("User denied access to location")
mapView.isHidden = false
case .notDetermined :
print("Location status not deteremined")
case .authorizedAlways : fallthrough
case . authorizedWhenInUse :
print("Location status is OK")
}
}
I think you missed to add key NSLocationWhenInUseUsageDescription in your Info.plist file.
Add this key to the usage description.
It should then show an iOS system pop-up to allow location access.
I have read your question and checked you given link for Map Tutorial. I found some code missing in your viewDidLoad method:
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter = 50
locationManager.startUpdatingLocation()
locationManager.delegate = self
placesClient = GMSPlacesClient.shared()
Without assign delegate to the object of CLLocationManager like locationManager.delegate = self
I don't think even your extension would be called (CLLocationManagerDelegate).
Also
As per #Let's_Create answer info.plist shold have following keys to explain the user how the app uses this.
dataNSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription
I have been looking at the google documentation to get the current location, but i am struggling to specify the location in the ViewDidLoad, as you can see i have set the Location fixed to Syndey Australia. In the google doc documentation when specifying the current location, they are using the "default location.coordinate" , i cannot access defaultLocation.coordinate in my code .
here is a link to the documenation : https://developers.google.com/maps/documentation/ios-sdk/current-place-tutorial
this is the code inside the viewDidLoad
GMSServices.provideAPIKey("AIzaSyARsPfNs54hrUAC4yKtHeu2jXfGjeA0b-E")
GMSPlacesClient.provideAPIKey("AIzaSyARsPfNs54hrUAC4yKtHeu2jXfGjeA0b-E ")
let camera = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 6.0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
// creating the marker //
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: -33.86, longitude: 151.20)
marker.title = "Sydney"
marker.snippet = "Australia"
marker.map = mapView
This is my extenstion code
extension MapsViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location : CLLocation = locations.last!
print("Location:\(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: zoomLevel)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
}
else {
mapView.animate(to: camera)
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
// display the map the default location
mapView.isHidden = false
case .denied :
print("User denied access to location")
mapView.isHidden = false
case .notDetermined :
print("Location status not deteremined")
case .authorizedAlways : fallthrough
case . authorizedWhenInUse :
print("Location status is OK")
}
}
You have added wrong code in your method searchLocationPressed, Please update it as follow.
#IBAction func searchLocationPressed(_ sender: UIBarButtonItem) {
let autocomplete = GMSAutocompleteViewController()
autocomplete.delegate = self
self.present(autocomplete, animated: true, completion: nil)
}
Your mistake is you are presenting UISearchController instead of GMSAutocompleteViewController.
I am using Google maps SDK with swift 3.I want to get the current location on a map but I am not able to get current location in the real device but in the simulator, it shows the location of apple.But on the real device, it shows the current location of set in the app scheme otherwise it shows the error "Error: Error Domain=kCLErrorDomain Code=0 "(null)"". I am using below code to get the current location.Please help me.This code works in ios 10 but not work in ios 9
#IBOutlet weak var view_map: GMSMapView!
let locationManager = CLLocationManager()
var didFindMyLocation = false
override func viewDidLoad() {
super.viewDidLoad()
view_map.isMyLocationEnabled = true
// //Location Manager code to fetch current location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
if #available(iOS 9.0, *) {
locationManager.allowsBackgroundLocationUpdates = true
locationManager.requestLocation()
}
locationManager.startUpdatingLocation()
}
//Location Manager delegates
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let camera = GMSCameraPosition.camera(withLatitude: (location?.coordinate.latitude)!, longitude: (location?.coordinate.longitude)!, zoom: 17.0)
self.view_map.animate(to: camera)
//Finally stop updating location otherwise it will come again and again in this delegate
self.locationManager.stopUpdatingLocation()
}
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
print("Location access was restricted.")
case .denied:
print("User denied access to location.")
// Display the map using the default location.
view_map.isHidden = false
case .notDetermined:
print("Location status not determined.")
case .authorizedAlways: fallthrough
case .authorizedWhenInUse:
print("Location status is OK.")
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
//Add these in your info.plist
<key>NSLocationAlwaysUsageDescription</key>
<string>Reason to access location background usage description</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Reason to access location usage description</string>