User location won't come up in simulator in Xcode - ios

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.

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
}

Get user location when app runs and re-center again after moving around using a button

I'm working on a project about MapKit using Swift 3. What the code below does is once I load the app the map will load in default. Then when the user presses the button it takes you to the user's location.
The way I want to fix this is I want it to load the user's location as soon as the app runs, and then when the user decides to move around the screen, she/he could hit the button and then recenter the user location again. Like how it works on Maps.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
// connecting the map from the mainBoard and refering to it as "myMap".....
#IBOutlet weak var myMap: MKMapView!
#IBAction func refLocation(_ sender: Any) {
manager.startUpdatingLocation()
}
let manager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
let span: MKCoordinateSpan = MKCoordinateSpanMake(0.0075,0.0075)
let myLocation :CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region: MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
myMap.setRegion(region, animated: true)
}
self.myMap.showsUserLocation = true
manager.stopUpdatingLocation()
}
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
}
}
It isn't clear what you're asking.
If you want to get a single location update you can use the function func requestLocation().
You could create a location manager (and set yourself as its delegate) in your view controller's viewDidLoad and call requestLocation() once.
Then call requestLocation() again in your button action.
Make your didUpdateLocations method always recenter the map. That way you'll receive one and only one update from clicking your button, and the map will recenter as soon as the update is received.
Try this code for Swift 3
import UIKit
import MapKit
import CoreLocation
class ViewController2: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var currentLocation = CLLocation()
var currentLat: Double!
var currentLon: Double!
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
myLocation()
}
func myLocation()
{
if currentLocation.coordinate.latitude == 0.00 || currentLocation.coordinate.longitude == 0.0
{
print("no location")
}
else
{
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled()
{
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
let locManager = CLLocationManager()
locManager.requestWhenInUseAuthorization()
if(CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways)
{
currentLocation = locManager.location!
}
print("currentLongitude: \(currentLocation.coordinate.longitude)")
print("currentLatitude: \(currentLocation.coordinate.latitude)")
currentLon = currentLocation.coordinate.longitude
currentLat = currentLocation.coordinate.latitude
let span = MKCoordinateSpanMake(0.2, 0.2)
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: currentLat, longitude: currentLon), span: span)
mapView.setRegion(region, animated: true)
}
}
#IBAction func MyLocationBtnPressed(_ sender: Any)
{
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: currentLat, longitude: currentLon), span: span)
mapView.setRegion(region, animated: true)
}
}
You don't have to call startUpdatingLocation() again because MapView always knows userLocation.
Replace
#IBAction func refLocation(_ sender: Any) {
manager.startUpdatingLocation()
}
with
#IBAction func refLocation(_ sender: Any) {
let region: MKCoordinateRegion = MKCoordinateRegionMake(myMap.userLocation.coordinate, myMap.region.span)
mapView.setRegion(region, animated: true)
}

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.

MKMapView seems to be nil?

I am new to Xcode and Swift and I am trying to simply make a map that shows the users current location and updates it. I have this so far:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
var mapp = MKMapView.self
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (CLLocationManager.locationServicesEnabled())
{
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.map.showsUserLocation = true
}
else
{
print("Location services are not enabled")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func loadView() {
//let camera = GMSCameraPosition.camera(withLatitude: 36.2108, longitude: -81.6774, zoom: 15.0)
//let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
//mapView.isMyLocationEnabled = true
//view = mapView
}
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.002, longitudeDelta: 0.002))
self.map.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
print("Errors: " + error.localizedDescription)
}
}
I have made a MapView in the storyboard and CTRL dragged it to the file (thus the #IBOutlet weak var map: MKMapView!). However, when I plug my phone in and simulate the app it gives me a "unexpectedly found nil while unwrapping an optional value" and after some print statements i found that it happened whenever I referenced the map variable. Why is this? Thanks!
In the comments of the original post, Rob answered the question:
"
Remove the loadView method. That's used only when you are programmatically creating views. When using storyboards (or NIBs), you put your configuration code in viewDidLoad, not loadView. – Rob"
thank you Rob

Resources