MKMapView seems to be nil? - ios

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

Related

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.

current location update on Google Maps SDK for Xcode not working

I have been trying to implement google maps in my application. The first step what I want to do is to simply get is:
1. Get the app to ask permission to use current location
2. Find the users current location and have a blue dot marker to mark it.
3. Update and centre the map around the users current location.
I have tried various methods to get this working but always end up with an error or doesn't work. Initially when I simulated the code below, it did come up with the dialog about requesting current location permission and a blue dot but in the following simulations this seems to have disappeared and when changing my current location in simulator (by going to edit schemes and changing default location) , the new current location did not update. I have a feeling that the code isn't working beyond viewDidLoad. where am I going wrong?
Please can I get some advice on how to rectify these problems and get the above points working (as well as the simulator to always ask for permission for current location). Currently the code runs with no errors but only shows me a map of the UK. (I have already added NSLocationWhenInUse and NSLocationAlwaysUsage.... into info.plist. And I have disabled all breakpoints. I have also tried resetting simulator)
import UIKit
import GoogleMaps
class FirstViewController: UIViewController,CLLocationManagerDelegate {
#IBOutlet weak var googlemaps: GMSMapView!
//this is the connection from the storyboard to the view controller
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 51.508742, longitude: -0.087891, zoom: 8.0)
let viewMap = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = viewMap
viewMap.isMyLocationEnabled = true
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
override func loadView() {
super.viewDidLoad()
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
// verification of granted permission while app in use
let locationManager = CLLocationManager()
let mapView = GMSMapView()
if status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
// if permission granted- starting updating location
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
//this is suppose to be button that is added when tapped centers to users location
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
mapView.camera = GMSCameraPosition.camera(withTarget: location.coordinate, zoom: 20)
self.view = mapView
locationManager.stopUpdatingLocation()
}
}
}
}
}
Thanks in advance! I have spent days trying to work this out with no success :(
I was able to solve this problem by updating Cocoapods and ensuring that GoogleMaps is in my Podfile. Then in my viewController I had the following code which executed perfectly.
import UIKit
import GoogleMaps
class FirstViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: GMSMapView!
var locationManager = CLLocationManager()
var vwGMap = GMSMapView()
override func viewDidLoad() {
super.viewDidLoad()
let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: 22.300000, longitude: 70.783300, zoom: 10.0)
vwGMap = GMSMapView.map(withFrame: self.view.frame, camera: camera)
vwGMap.camera = camera
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
locationManager.distanceFilter = 500
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
self.view = vwGMap
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.authorizedWhenInUse)
{
vwGMap.isMyLocationEnabled = true
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let newLocation = locations.last
vwGMap.camera = GMSCameraPosition.camera(withTarget: newLocation!.coordinate, zoom: 15.0)
vwGMap.settings.myLocationButton = true
self.view = self.vwGMap
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(newLocation!.coordinate.latitude, newLocation!.coordinate.longitude)
marker.map = self.vwGMap
}
}

fatal error: unexpectedly found nil while unwrapping an Optional value while printing on UILabel

I'm trying to display the users current location and calculate the distance he traveled and i'm getting error at displaying it on distance1.text, can somebody please help me. Thanks in advance and I'm very new to iOS app development, currently using swift3
import UIKit
import MapKit
import CoreLocation
class MapView1: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var distance1: UILabel!
let locationManager = CLLocationManager()
var startLocation:CLLocation!
var lastLocation: CLLocation!
var traveledDistance:Double = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
startLocation = nil
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Location Delegate Methods
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center1 = CLLocationCoordinate2D(latitude: location!.coordinate.latitude , longitude: location!.coordinate.longitude)
let region1 = MKCoordinateRegion(center: center1, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region1, animated: true)
self.locationManager.stopUpdatingLocation()
if startLocation == nil {
startLocation = location
}
let distanceBetween: CLLocationDistance =
location!.distance(from: startLocation)
distance1.text = String(format: "%.2f", distanceBetween)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error: " + error.localizedDescription)
}
}

'MKMapView' / 'showsUserLocation = true' causing error with modal segue

I am developing a small map application which allows users to view their current location. I have the relevant code to perform this and it seems to work as expected:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UISearchBarDelegate, UIPopoverPresentationControllerDelegate {
// CLlocation
var location: CLLocation!
let locationManager = CLLocationManager()
// Map variables
var searchController:UISearchController!
var annotation:MKAnnotation!
var localSearchRequest:MKLocalSearchRequest!
var localSearch:MKLocalSearch!
var localSearchResponse:MKLocalSearchResponse!
var error:NSError!
var pointAnnotation:MKPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
// IBOutlets
#IBOutlet weak var placesMap: MKMapView!
// Location function
func locationManager(manager: CLLocationManager, didUpdateqLocations 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.placesMap.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Error code: " + error.localizedDescription)
}
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.placesMap.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
However, when I launch a modal segue to the 'About' page, from a popover (pictured below), the app crashes:
I viewed the error given to me in the terminal, this was
fatal error: unexpectedly found nil while unwrapping an Optional value
Xcode pointed me to this particular line in my viewDidLoad function:
self.placesMap.showsUserLocation = true
When I delete that particular line from my code, the location feature no longer functions, this is obvious. I have checked the outlet to the MKMapView and it seems to be correct.
I really don't know how to avoid this error, or for certainty what is causing it, so any help is appreciated.
Basically, something is making the placesMap deallocate and then viewDidLoad is being called. You might try making the placesMap optional instead of force unwrapping it, so change the ! to a ? on the property and then chain the optional into the call sites of placesMap, so self.placesMap.showsUserLocation becomes self.placesMap?.showsUserLocation and self.placesMap.setRegion(region, animated: true) becomes self.placesMap?.setRegion(region, animated: true)

SWIFT Thread 1: EXC Bad instruction XCODE IOS

I am very new to stackexchange so please let me know if i need to provide more information.
I tried to install the Corelocation and Mapkit and use them togheter. Every since i followed Vea Software Tutorial i have recived the following error:
Thread 1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode=0x0)
In the compiler it says
fatal error: Unexpectedly found nil while unwrapping an Optional
Value(llDB)
The error is appering right at this line, but when i delete it, it appears at another Mapkit/Location core line. The error:
self.mapView.showsUserLocation = true
EDIT: When i remove the line above, the same error appears on
self.mapView.setRegion(region, animated: true)
I have been searching around for a while on the internet but nothing really helps me out. Thank you for your time.
If you need the whole viewcontroller code. Here it is.
import UIKit
import Parse
import CoreLocation
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
#IBOutlet var UsernameTextField: UITextField!
#IBOutlet var PasswordTF: UITextField!
#IBOutlet var EmailTF: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Location Delegate Methods
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: 1, longitudeDelta: 1))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Error:" + error.localizedDescription)
}
}
This just an hypothesis by I noticed you use
self.mapView.setRegion(region, animated: true)
in the CLLocationManager delegate and start updating before mapView is actually showing (i.e. in viewDidLoad).
Could it be that mapView is trying to update its visual states before being installed in the view hierarchy ?

Resources