Find location name swift maps - ios

I am creating a map using swift. How can i find the name of my current location as saved on Apple maps, like lets say I am at Walmart, how do i get it to print out the name of the location, and if the location it just prints out an address.
My current code is
class MapVC: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let manager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let mylocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(mylocation, span)
map.setRegion(region, animated: true)
print(location.coordinate)
print(location.coordinate.latitude)
print(location.speed)
self.map.showsUserLocation = true
self.map.showsPointsOfInterest = true
}
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
}

You can use iOS native API to convert longitude and latitude to place name:
func reverseGeocodeLocation(_ location: CLLocation,
completionHandler: #escaping CLGeocodeCompletionHandler)
For example:
var geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in
})
Get the place name by getting the first object of placemarks which is of type CLPlacemark. Then the CLPlacemark's name property is what you are after.

Related

Cannot convert value of type 'CLLocationCoordinate2D' to expected argument type 'CLLocationDegrees' (aka 'Double')

I have getting user's current location but getting this error at this line
let region : MKCoordinateRegion = MKCoordinateSpanMake(myLocation, span)
I am getting error at myLocation in above line
Cannot convert value of type 'CLLocationCoordinate2D' to expected argument type 'CLLocationDegrees' (aka 'Double')
I think there may be type casting problem or similar.
What should I do to handle this error I researched a lot of examples but none helped me.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
let manager = CLLocationManager()
#IBOutlet weak var myMap: MKMapView!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span : MKCoordinateSpan = MKCoordinateSpanMake(1, 1)
let myLocation : CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region : MKCoordinateRegion = MKCoordinateSpanMake(myLocation, span)
myMap.setRegion(region, animated: true)
self.myMap.showsUserLocation = true
}
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You want MKCoordinateRegionMake, not MKCoordinateSpanMake.
And there's lots of other fixes you should make:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span = MKCoordinateSpanMake(0.01, 0.01)
let myLocation = location.coordinate
let region = MKCoordinateRegionMake(myLocation, span)
myMap.setRegion(region, animated: true)
self.myMap.showsUserLocation = true
}

Downcast from 'CLLocation?' to 'CLLocation' only unwraps optionals; did you mean to use '!'?

I'm trying to display the users current location on a map view but I'm getting an error on the first line of the location manager function
Here is my code
import UIKit
import MapKit
class FirstViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapkitView: MKMapView!
var locationManager: CLLocationManager!
override func viewDidLoad()
{
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last as! CLLocation
let center = CLLocationCoordinate2DMake(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapkitView.setRegion(region, animated: true)
}
}
The error I'm getting is "Downcast from 'CLLocation?' to 'CLLocation' only unwraps optionals; did you mean to use '!'?
on line let location = locations.last as! CLLocation
You are force-casting an Optional CLLocationto CLLocation, that is why Swift suggests to simply force unwrap it:
let location = locations.last!
This version (and yours) will crash if locations is empty.
Thus I recommend to never force unwrap anything and use guardinstead:
guard let location = locations.last else {
return
}

User location won't come up in simulator in Xcode

I'm new to app development and I'm trying to get the user location to come up in the simulator but I keep getting the Use of unresolved identifier error. I have looked at other questions, which are very specific to their own projects, and have tried to approach my own app in a similar way but to not avail. Any help, por favor? Here's my code, and a link to a screenshot of Xcode.
import UIKit
import MapKit
import CoreLocation
class SecondViewController: UIViewController, CLLocationManagerDelegate {
//Map
#IBOutlet weak var map: MKMapView!
let manager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{ let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
self.map.showsUserLocation = true
}
override func viewDidLoad()
{
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
//This is where I get an error
map.setRegion(region, animated: true)**
}
Error: Use of unresolved identifier
Your let region:MKCoordinateRegion is a local identifier inside your delegate method:
func locationManager(_:didUpdateLocations) {...}
This is why you are getting Use of unresolved identifier. Make this identifier accessible throughout the class, the error will be gone. Like:
class SecondViewController: UIViewController, CLLocationManagerDelegate {
//Map
#IBOutlet weak var map: MKMapView!
var region = MKCoordinateRegion()
.......
.......
}
N.B: But this won't let you see anything in the map. Best way to see any output from your MapView is to put map.setRegion(region, animated: true) inside your delegate method:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.first
let span = MKCoordinateSpanMake(0.01, 0.01)
let myLocation = CLLocationCoordinate2DMake((location?.coordinate.latitude)!, (location?.coordinate.longitude)!)
region = MKCoordinateRegionMake(myLocation, span)
map.setRegion(region, animated: true)
}
Use MKCoordinateRegion instance before viewdidload method
You can follow below code for reference.
class Test: UIViewController {
var region = MKCoordinateRegion()
override func viewDidLoad() {
super.viewDidLoad()
region = MKCoordinateRegionMake(myLocation, span)
}
}
You are getting Error because
the variable region inside viewDidLoad() method do not have access of region variable inside
viewDidLoad() method
//This is where I get an error
map.setRegion(region, animated: true)**
Solution :
Make region variable global to class so that that can be accessed from anywhere you want to.
Instead of this line inside func locationManager
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation,span)
Use
self.region = MKCoordinateRegionMake(myLocation,span)
Here is complete code That you can use.
import UIKit
import MapKit
import CoreLocation
class SecondViewController: UIViewController, CLLocationManagerDelegate {
//Map
#IBOutlet weak var map: MKMapView!
//global variable
var region:MKCoordinateRegion = MKCoordinateRegion()
let manager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{ let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
self.region = MKCoordinateRegionMake(myLocation, span)
self.map.showsUserLocation = true
}
override func viewDidLoad()
{
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
//This is where I get an error
map.setRegion(region, animated: true)**
}
//
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And more important if you are using simulator then you have to enable location simulation.

swift 3 error using MapKit

I'm making a map
Add the two variables in info.plist "Privacy - Location When Usage Description", "Privacy - Location Always Usage Description"
Error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid Region '
My code:
import UIKit
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
var manager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
manager = CLLocationManager()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
let uilpgr = UILongPressGestureRecognizer(target: self, action:Selector(("action:")))
uilpgr.minimumPressDuration = 2.0
map.addGestureRecognizer(uilpgr)
}
func action(gestureRecognizer:UIGestureRecognizer){
if gestureRecognizer.state == UIGestureRecognizerState.began{
let touchPoint = gestureRecognizer.location(in: self.map)
let newCoordinate = self.map.convert(touchPoint, toCoordinateFrom: self.map)
let annotation = MKPointAnnotation()
annotation.coordinate = newCoordinate
annotation.title = "Meu lugar"
self.map.addAnnotation(annotation)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0]
let latitude = userLocation.coordinate.latitude
let longitude = userLocation.coordinate.longitude
let coordinate = CLLocationCoordinate2DMake(longitude,latitude)
let latDelta: CLLocationDegrees = 0.01
let lonDelta: CLLocationDegrees = 0.01
let span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
let region:MKCoordinateRegion = MKCoordinateRegionMake(coordinate, span)
self.map.setRegion(region, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I think you forgot to import the CoreLocation framework. I don't think you are getting a valid location object back from the delegate method. Please, import the CoreLocation framework and test it again.
Your code in the locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) is redundant as you can just call self.map.setUserTrackingMode(.follow, animated: true)
If the user were to pan the map, user tracking will become disabled, so you would need to use this delegate mapView(_ mapView: MKMapView, didChange mode: MKUserTrackingMode, animated: Bool) to update the user tracking mode.

Show Current Location and Update Location in MKMapView in Swift

I am learning how to use the new Swift language (only Swift, no Objective-C). To do it, I want to do a simple view with a map (MKMapView). I want to find and update the location of the user (like in the Apple Map app).
I tried this, but nothing happened:
import MapKit
import CoreLocation
class MapView : UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
}
Could you please help me?
You have to override CLLocationManager.didUpdateLocations (part of CLLocationManagerDelegate) to get notified when the location manager retrieves the current location:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last{
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)
}
}
NOTE: If your target is iOS 8 or above, you must include the NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in your Info.plist to get the location services to work.
100% working, easy steps and tested
Import libraries:
import MapKit
import CoreLocation
set delegates:
CLLocationManagerDelegate,MKMapViewDelegate
Take variable:
let locationManager = CLLocationManager()
write this code on viewDidLoad():
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
if let coor = mapView.userLocation.location?.coordinate{
mapView.setCenter(coor, animated: true)
}
Write delegate method for location:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
mapView.mapType = MKMapType.standard
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: locValue, span: span)
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = locValue
annotation.title = "Javed Multani"
annotation.subtitle = "current location"
mapView.addAnnotation(annotation)
//centerMap(locValue)
}
Do not forgot to set permission in info.plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
It's look like:
For swift 3 and XCode 8 I find this answer:
First, you need set privacy into info.plist. Insert string NSLocationWhenInUseUsageDescription with your description why you want get user location. For example, set string "For map in application".
Second, use this code example
#IBOutlet weak var mapView: MKMapView!
private var locationManager: CLLocationManager!
private var currentLocation: CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// Check for Location Services
if CLLocationManager.locationServicesEnabled() {
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
}
// MARK - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
defer { currentLocation = locations.last }
if currentLocation == nil {
// Zoom to user location
if let userLocation = locations.last {
let viewRegion = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 2000, 2000)
mapView.setRegion(viewRegion, animated: false)
}
}
}
Third, set User Location flag in storyboard for mapView.
MyLocation
is a Swift iOS Demo.
You can use this demo for the following:
Show the current location.
Choose other location: in this case stop tracking the location.
Add a push pin to a MKMapView(iOS) when touching.
Hi Sometimes setting the showsUserLocation in code doesn't work for some weird reason.
So try a combination of the following.
In viewDidLoad()
self.mapView.showsUserLocation = true
Go to your storyboard in Xcode, on the right panel's attribute inspector tick the User location check box, like in the attached image. run your app and you should be able to see the User location
Swift 5.1
Get Current Location and Set on MKMapView
Import libraries:
import MapKit
import CoreLocation
set delegates:
CLLocationManagerDelegate , MKMapViewDelegate
Declare variable:
let locationManager = CLLocationManager()
Write this code on viewDidLoad():
self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
if let coor = mapView.userLocation.location?.coordinate{
mapView.setCenter(coor, animated: true)
}
Write delegate method for location:
func locationManager(_ manager: CLLocationManager, didUpdateLocations
locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
mapView.mapType = MKMapType.standard
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: locValue, span: span)
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = locValue
annotation.title = "You are Here"
mapView.addAnnotation(annotation)
}
Set permission in info.plist *
<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
For Swift 2, you should change it to the following:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)
}
You just need to set the userTrackingMode of the MKMapView. If you only want to display and track the user location and implement the same behaviour as the Apple Maps app uses, there is no reason for writing additional code.
mapView.userTrackingMode = .follow
See more at https://developer.apple.com/documentation/mapkit/mkmapview/1616208-usertrackingmode .
you have to override CLLocationManager.didUpdateLocations
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
locationManager.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)
}
you also have to add NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to your plist setting Result as value
In Swift 4, I had used the locationManager delegate function as defined above ..
func locationManager(manager: CLLocationManager!,
didUpdateLocations locations: [AnyObject]!) {
.. but this needed to be changed to ..
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
This came from .. https://github.com/lotfyahmed/MyLocation/blob/master/MyLocation/ViewController.swift - thanks!
mapView.showsUserLocation = true
Create UIButton and add this action
#IBAction func showCurrentLocation(_ sender: Any) {
let coordinate = mapView.userLocation.coordinate
let center = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
}

Resources