Offline map tiles have stopped displaying - ios

I have downloaded tiles for a small town in zooms 15 to 18. They were displaying as expected but now don't.
I was using xcode 7 with swift 2 on Yosemite. I'm now with xcode 8.1 with swift 3 on sierra. I'm pretty sure the problem started before the upgrade, but have no time machine to go back. I upgraded because I wanted to test the app on my IPad 2, got the message that xcode wasn't compatible with the ios on the ipad, then got a message that xcode 8.1 cant be loaded to Yosemite hence upgrade to sierra.
The code is below. And the console output bellow that. No error given
//
// MapViewController.swift
// button scale
//
// Created by Colin McGarry on 24/03/16.
// Copyright © 2016 Colin McGarry. All rights reserved.
//
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController /*, MKMapViewDelegate*/{
var guideData: GuideData?
var dataM:[GuideData] = [GuideData]()
var placeNumb = 0
var modifyingMap = true
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let IS_RETINA = (UIScreen.mainScreen().respondsToSelector(#selector(UIScreen.displayLinkWithTarget(_:selector:))) && (UIScreen.mainScreen().scale >= 2.0))
// from shankar map
if IS_RETINA {
print("Is Retina")
} else {
print("not retina")
}
zoomToRegion()
let annotations = getMapAnnotations()
// Add mappoints to Map
mapView.addAnnotations(annotations)
// end shankar map
//Get the URL template to the map tiles
let baseURL = NSBundle.mainBundle().bundleURL.absoluteString
let urlTemplate = baseURL!.stringByAppendingString("osmm/{z}/{x}/{y}.png/")
//let urlTemplate = baseURL.stringByAppendingString("two/{z}/{x}/{y}#2x.png/")
//let urlTemplate = "http://tile.openstreetmap.org/{z}/{x}/{y}.png"
print(urlTemplate)
let carte_indice = MKTileOverlay(URLTemplate:urlTemplate)
carte_indice.geometryFlipped = false
carte_indice.canReplaceMapContent = true
//carte_indice.tileSize = CGSize(width: 512, height: 512)
carte_indice.maximumZ = 16
carte_indice.minimumZ = 18
self.mapView.addOverlay(carte_indice)
}
/// from shankar map
func zoomToRegion() {
let location = CLLocationCoordinate2D(latitude: 49.275, longitude: -0.7028)
let region = MKCoordinateRegionMakeWithDistance(location, 500.0, 500.0)
mapView.setRegion(region, animated: true)
}
//MARK:- Annotations
func getMapAnnotations() -> [Stands] {
var annotations:Array = [Stands]()
//load plist file
var stands: NSArray?
if let path = NSBundle.mainBundle().pathForResource("stands", ofType: "plist") {
stands = NSArray(contentsOfFile: path)
}
//iterate and create annotations
if let items = stands {
for item in items {
let lat = item.valueForKey("lat") as! Double
let long = item.valueForKey("long")as! Double
let annotation = Stands(latitude: lat, longitude: long)
let tit = item.valueForKey("title") as! String
let numb = item.valueForKey("no") as! Int
annotation.title = "\(numb) \(tit)"
annotation.no = numb
// new added
// annotation.enabled = true
// annotation.canShowCallOut = true
// end added
annotations.append(annotation)
}
}
return annotations
}
// end From Shankar map
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
// 1
let identifier = "Stand"
// 2
if annotation.isKindOfClass(Stands.self) {
// 3
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
//4
annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView!.canShowCallout = true
// 5
let btn = UIButton(type: .DetailDisclosure)
annotationView!.rightCalloutAccessoryView = btn
} else {
// 6
annotationView!.annotation = annotation
}
return annotationView
}
// 7
return nil
}
func mapView( mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
let standM = view.annotation as! Stands
let placeName = standM.title
let placeInfo = standM.title
placeNumb = standM.no!
/*
let ac = UIAlertController(title: placeName, message: placeInfo, preferredStyle: .Alert)
ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(ac, animated: true, completion: nil) */
performSegueWithIdentifier("MapToText", sender: self)
}
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
// enforce maximum zoom level
let place = mapView.visibleMapRect
if( place.origin.x < 133686298
|| place.origin.x > 133697376
|| place.origin.y < 91864219
|| place.origin.y > 91874305
)
{
zoomToRegion()
}
print("alt \(mapView.camera.altitude)")
let maxAlt = 3000.00
if (mapView.camera.altitude > maxAlt && self.modifyingMap)
{
self.modifyingMap = false
// prevents strange infinite loop case
self.mapView.zoomEnabled = false
/* self.mapView.scrollEnabled = false
self.mapView.userInteractionEnabled = false
*/
print("place \(place)")
self.mapView.camera.altitude = maxAlt
self.modifyingMap = true
print("alt>\(maxAlt)")
} else {
self.mapView.zoomEnabled = true
print("place2 \(place)")
print("x \(place.origin.x)")
print(" alt less than \(maxAlt)")
print(mapView.camera.altitude)
}
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer!
{
print("call overlay")
if overlay is MKTileOverlay
{
print("is MKTileoverlay")
let renderer = MKTileOverlayRenderer(overlay:overlay)
renderer.alpha = 0.8
return renderer
}
return nil
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "MapToText" {
let webviewController:webViewController = segue.destinationViewController as! webViewController
webviewController.index = placeNumb - 1
// webviewController.standTitle = sender as! MKAnnotationView
webviewController.inde = placeNumb - 1
print("prepSeg \(webviewController.inde)")
}
}
}
console output
/Users/colinmcgarry/Library/Developer/CoreSimulator/Devices/4F5E35FC-45F9-4A16-8A0A-1AFD51616CCA/data/Containers/Bundle/Application/046B53E5-D3CD-4E7A-926D-7D77E069AAA0/button scale.app/stands.plist
Optional("/Users/colinmcgarry/Library/Developer/CoreSimulator/Devices/4F5E35FC-45F9-4A16-8A0A-1AFD51616CCA/data/Containers/Bundle/Application/046B53E5-D3CD-4E7A-926D-7D77E069AAA0/button scale.app/2page.html")
Is Retina
alt 1100.94691259802
place2 MKMapRect(origin: __C.MKMapPoint(x: 133691120.58898854, y: 91870217.34526816), size: __C.MKMapSize(width: 5123.4971518665552, height: 6063.3100336045027))
x 133691120.588989
alt less than 3000.0
1100.94691259802
file:///Users/colinmcgarry/Library/Developer/CoreSimulator/Devices/4F5E35FC-45F9-4A16-8A0A-1AFD51616CCA/data/Containers/Bundle/Application/046B53E5-D3CD-4E7A-926D-7D77E069AAA0/button%20scale.app/osmm/{z}/{x}/{y}.png/
call overlay
is MKTileoverlay

I found the problem. But it's not in the code I included.
I had put min and max zoom. When I changed the values I interchanged min and max
overlay.maximumZ = 15
overlay.minimumZ = 17
These conditions are mutually contradicting so overlay didn't show.
if I'd written min above max I might have noticed before.

Related

MKAnnotation doesn't appear

I'm writing flight ticket's app and have some troubles with map annotation's
So we have view, that showing all ticket information, and map with departure city and destination
Here's view loading :
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
configureView(showingReturnData: showingReturnData, fromTicket: showingTicketNow)
designSetup()
mapSetting()
}
Converting to coordinates :
func gettingCoordinates(cityString: String) -> CLLocationCoordinate2D {
let geocoder = CLGeocoder()
var returningCoordinate = CLLocationCoordinate2D()
geocoder.geocodeAddressString(cityString) { (placemarksArray, error) in
if error == nil && placemarksArray?.count != 0 {
let placemark = placemarksArray![0]
print(placemark.country, placemark.name,
placemark.location!.coordinate.longitude,
placemark.location!.coordinate.latitude)
//Here output:
Optional("Japan") Optional("Tokyo") 139.6917 35.689506
Optional("Russia") Optional("Moscow") 37.60946 55.7615902
returningCoordinate.longitude = placemark.location!.coordinate.longitude
returningCoordinate.latitude = placemark.location!.coordinate.latitude
} else {
print(error!)
}
}
return returningCoordinate
}
And then adding annotations to map, but It's always the same place, near Africa in ocean
func mapSetting() {
let fromPlacemark = gettingCoordinates(cityString: showingTicketNow.fromCityName)
let toPlacemark = gettingCoordinates(cityString: showingTicketNow.toCityName)
let fromAnnotation = MKPointAnnotation()
fromAnnotation.title = fromCityName.text!
fromAnnotation.coordinate = fromPlacemark
mapView.addAnnotation(fromAnnotation)
let toAnnotation = MKPointAnnotation()
toAnnotation.title = toCityName.text!
toAnnotation.coordinate = toPlacemark
mapView.addAnnotation(toAnnotation)
let coordinateRegion = MKCoordinateRegion(center: toPlacemark, latitudinalMeters:
10000, longitudinalMeters: 10000)
mapView.setRegion(coordinateRegion, animated: true)
}
What i'm doing wrong?

My button I created progmatically to push from my app the Apple Maps app stopped working.. why?

I have a navigation app I am working on which works like a normal maps app, allowing you to search for locations through a search table etc. So in my app I have a button which allows for the user to add multiple annotations (be default every time the user clicks a new result in the searchtable I have it set to remove the most recent annotation) and find the centerpoint between all these areas. The code then shifts that centerpoint to the closest address so there is a place to get directions to, not just lat and long. Anyway, I have it set so that when the user taps the annotation, a button appears right above it, and the button is supposed to send you to apple maps with the preset route already loaded in. This worked until recently. Here is the code that carries this button's actions out:
extension ViewController : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.pinTintColor = UIColor.red
pinView?.canShowCallout = true
let smallSquare = CGSize(width: 30, height: 30)
let button = UIButton(frame: CGRect(origin: (CGPoint()), size: smallSquare))
button.setBackgroundImage(UIImage(named: "car"), for: [])
button.addTarget(self, action: #selector(getDirections), for: UIControlEvents.touchUpInside)
pinView?.leftCalloutAccessoryView = button
return pinView
}
}
and in the class
#objc func getDirections(){
if let selectedPin = selectedPin {
let mapItem = MKMapItem(placemark: selectedPin)
let launchOptions = [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]
mapItem.openInMaps(launchOptions: launchOptions)
}
}
Could it be something weird with the objective C function? This is the code I recently added that potentially could have caused the issue, though I really don't know:
func resolveAddress(for averageCoordinate: CLLocationCoordinate2D, completion: #escaping (MKPlacemark?) -> () ) {
let geocoder = CLGeocoder()
let averageLocation = CLLocation(latitude: averageCoordinate.latitude, longitude: averageCoordinate.longitude)
geocoder.reverseGeocodeLocation(averageLocation) { (placemarks, error) in
guard error == nil,
let placemark = placemarks?.first
else {
completion(nil)
return
}
completion(MKPlacemark(placemark: placemark ))
}
}
#IBAction func middleFinderButton(_ sender: Any) {
let totalLatitude = mapView.annotations.reduce(0) { $0 + $1.coordinate.latitude }
let totalLongitude = mapView.annotations.reduce(0) { $0 + $1.coordinate.longitude }
let averageLatitude = totalLatitude/Double(mapView.annotations.count)
let averageLongitude = totalLongitude/Double(mapView.annotations.count)
let centerPoint = MKPointAnnotation()
centerPoint.coordinate.latitude = averageLatitude
centerPoint.coordinate.longitude = averageLongitude
mapView.addAnnotation(centerPoint)
resolveAddress(for: centerPoint.coordinate) { placemark in
if let placemark = placemark {
self.mapView.addAnnotation(placemark)
} else {
self.mapView.addAnnotation(centerPoint)
}
}
print(totalLatitude)
print(totalLongitude)
print(averageLatitude)
print(averageLongitude)
print(centerPoint.coordinate)
}
}
Anyone have an idea why this button isn't working and pushing the app to maps with a preset route? could it be a glitch with the simulator(it used to work so I doubt it)? Thanks.

Pin correct Annotation Image parse backend

I have setup a map in which data is loaded from the parse backend. In map I want to display the images that are already saved in Assets folder. Image should be equal to Player Name . There latitude and longitude is already saved in the Parse.
The position of the player is displayed correctly but the image is not being showed correctly , if the last name in the playerName column is Sachin then the image is same for all the player annotation pin.
I want to apply like if playerName == annotation.title the image of rahul should be displayed .
Console Print :
26.6481591686873 , 77.1777485870544 Sachin
27.655116868732 , 77.17778705437 Rahul
28.6479996556687 , 77.1779252453013 Matt
28.6480628887157 , 77.1779590059193 Virat
28.1578689896 , 76.989079 Sachin
var playerName:String!
override func viewDidLoad() {
super.viewDidLoad()
query.findObjectsInBackgroundWithBlock { (posts, error) in
if error == nil {
let myPosts = posts! as [PFObject]
for posts in myPosts {
let latitude12 = posts["playerLat"] as! Double
let longitude12 = posts["playerLong"] as! Double
let playName = posts["playerName"] as! String
self.playerName = posts["playerName"] as! String
print(latitude12,"," , longitude12, playerName)
let annotation = MKPointAnnotation()
//let customAnno = MKAnnotationView()
let locationCoordinate = CLLocationCoordinate2DMake(latitude12, longitude12)
annotation.coordinate = locationCoordinate
//customAnno.enabled = true
let anno = self.mapView.dequeueReusableAnnotationViewWithIdentifier("places")
if anno == nil {
// if annotation.title == "Sachin" {
//}
annotation.title = playerName
self.mapView.addAnnotations([annotation])
} else {
anno?.annotation = annotation
}
}
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "customAnnotationView"
let annotation1 = MKPointAnnotation()
// custom image annotation
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if (annotationView == nil) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}
else {
annotationView!.annotation = annotation
}
if annotation1.title == "Rahul" {
annotationView!.image = UIImage(named: "Rahul")}
else if annotation1.title == "Sachin"{
annotationView!.image = UIImage(named: "Sachin")
}
return annotationView
}
I have tried all codes but the image is same for all the players image.

Remove annotations from map and replace with updated annotations (qTree)

I am currently working on adding cluster annotations to my map view. Everything is working fine with the exception of a couple of things. First of all, I need to refresh the annotations on the map when the user leaves and returns to the view. At the moment this sort of works... The problem is that rather than removing the annotations and adding the new ones, the new ones are just being added in addition of the old ones so there are multiplying each time.
The next issue is that each annotation displays the distance the user is from that annotation, however the annotations are set up before the user's location is found. I assume I will just have to remove and replace the annotations once the location is found, but then I run into the issue of the annotations duplicating again.
This is my code:
override func viewDidAppear(animated: Bool) {
println(rideArray.count)
setUpMapView()
}
func setUpMapView() {
rideArray = ((DataManager.sharedInstance.rideArray) as NSArray) as! [Ride]
myLocation = mapView.userLocation.coordinate as CLLocationCoordinate2D
zoomRegion = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2D(latitude: parkPassed.latitude!, longitude: parkPassed.longitude!), 1000, 1000)
mapView.setRegion(zoomRegion, animated: true)
mapView.delegate = self
for ride in rideArray {
println("Location: \(mapView.userLocation.coordinate.latitude)")
var subtitle = ""
if mapView.userLocation.location == nil {
subtitle = "Distance unavailable"
} else {
let userLocation = CLLocation(latitude: mapView.userLocation.coordinate.latitude, longitude: mapView.userLocation.coordinate.longitude)
let annotationLocation = CLLocation(latitude: ride.latitude!, longitude: ride.longitude!)
var distance = Int(CLLocationDistance(annotationLocation.distanceFromLocation(userLocation)))
if distance > 1000 {
distance = distance / 1000
subtitle = "\(distance) kilometers"
} else {
subtitle = "\(distance) meters"
}
}
let annotation = RideAnnotation(coordinate: CLLocationCoordinate2DMake(ride.latitude!, ride.longitude!), title: ride.name!, subtitle: subtitle)
self.qTree.insertObject(annotation)
}
var leftSwipe = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
var rightSwipe = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
leftSwipe.direction = .Left
rightSwipe.direction = .Right
view.addGestureRecognizer(leftSwipe)
view.addGestureRecognizer(rightSwipe)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation.isKindOfClass(QCluster.classForCoder()) {
let PinIdentifier = "PinIdentifier"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(ClusterAnnotationView.reuseId()) as? ClusterAnnotationView
if annotationView == nil {
annotationView = ClusterAnnotationView(cluster: annotation)
}
annotationView!.cluster = annotation
return annotationView
} else if annotation.isKindOfClass(RideAnnotation.classForCoder()) {
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("RideAnnotation")
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "RideAnnotation")
pinView?.canShowCallout = true
pinView?.rightCalloutAccessoryView = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as! UIButton
pinView?.rightCalloutAccessoryView.tintColor = UIColorFromRGB(0x424242)
let rideTimeView = UIView()
rideTimeView.frame = CGRectMake(5, 5, 50, 50)
rideTimeView.layer.cornerRadius = 25
let waitTimeLabel = UILabel()
waitTimeLabel.frame = CGRectMake(0, 0, 50, 50)
if DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime! == "Closed" {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)"
rideTimeView.backgroundColor = getColorFromNumber(80)
waitTimeLabel.font = UIFont(name: "Avenir", size: 15)
} else {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)m"
rideTimeView.backgroundColor = getColorFromNumber(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!.toInt()!)
waitTimeLabel.font = UIFont(name: "Avenir", size: 20)
}
waitTimeLabel.textAlignment = NSTextAlignment.Center
waitTimeLabel.textColor = UIColor.whiteColor()
waitTimeLabel.adjustsFontSizeToFitWidth = true
waitTimeLabel.numberOfLines = 1
rideTimeView.addSubview(waitTimeLabel)
pinView.leftCalloutAccessoryView = rideTimeView
pinView?.image = UIImage(named: "rideMapAnnotation")
} else {
pinView?.annotation = annotation
let rideTimeView = UIView()
rideTimeView.frame = CGRectMake(5, 5, 50, 50)
rideTimeView.layer.cornerRadius = 25
let waitTimeLabel = UILabel()
waitTimeLabel.frame = CGRectMake(0, 0, 50, 50)
if DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime! == "Closed" {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)"
rideTimeView.backgroundColor = getColorFromNumber(80)
waitTimeLabel.font = UIFont(name: "Avenir", size: 15)
} else {
waitTimeLabel.text = "\(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!)m"
rideTimeView.backgroundColor = getColorFromNumber(DataManager.sharedInstance.getRideByName(annotation.title!)!.waitTime!.toInt()!)
waitTimeLabel.font = UIFont(name: "Avenir", size: 20)
}
waitTimeLabel.textAlignment = NSTextAlignment.Center
waitTimeLabel.textColor = UIColor.whiteColor()
waitTimeLabel.adjustsFontSizeToFitWidth = true
waitTimeLabel.numberOfLines = 1
rideTimeView.addSubview(waitTimeLabel)
pinView.leftCalloutAccessoryView = rideTimeView
}
return pinView
}
return nil
}
func reloadAnnotations(){
if self.isViewLoaded() == false {
return
}
self.cacheArray.removeAll(keepCapacity: false)
let mapRegion = self.mapView.region
let minNonClusteredSpan = min(mapRegion.span.latitudeDelta, mapRegion.span.longitudeDelta) / 5
let objects = self.qTree.getObjectsInRegion(mapRegion, minNonClusteredSpan: minNonClusteredSpan) as NSArray
for object in objects {
if object.isKindOfClass(QCluster){
let c = object as? QCluster
let neighbours = self.qTree.neighboursForLocation((c?.coordinate)!, limitCount: NSInteger((c?.objectsCount)!)) as NSArray
for neighbour in neighbours {
let tmp = self.rideArray.filter({
return $0.name == (neighbour.title)!!
})
if find(self.cacheArray, tmp[0]) == nil {
self.cacheArray.insert(tmp[0], atIndex: self.cacheArray.count)
}
}
} else {
let tmp = self.rideArray.filter({
return $0.name == (object.title)!!
})
if find(self.cacheArray, tmp[0]) == nil {
self.cacheArray.insert(tmp[0], atIndex: self.cacheArray.count)
}
}
}
let annotationsToRemove = (self.mapView.annotations as NSArray).mutableCopy() as! NSMutableArray
annotationsToRemove.removeObject(self.mapView.userLocation)
annotationsToRemove.removeObjectsInArray(objects as [AnyObject])
self.mapView.removeAnnotations(annotationsToRemove as [AnyObject])
let annotationsToAdd = objects.mutableCopy() as! NSMutableArray
annotationsToAdd.removeObjectsInArray(self.mapView.annotations)
self.mapView.addAnnotations(annotationsToAdd as [AnyObject])
}
func mapView(mapView: MKMapView!, regionDidChangeAnimated animated: Bool) {
viewChanged = true
self.reloadAnnotations()
}
I apologise for the extensive amount of code, but it all had to be included.
Anyone have any suggestions as to how I can remove the annotations and re-add them once the view appears?
Thanks!
EDIT:
The second issue is now resolved. Here is a bit more detail in regards to the situation and issue:
Basically each annotation represents a ride in a theme park and displays the ride name, current wait time and distance to that ride. At the moment since I am calling setUpMapView() when the view appears, all of the ride annotations are being added to the qTree each time, but are not being removed. This is the issue that I am trying to resolve, but I can't find a way to remove them from the qTree.
MKMapView has the method removeAnnotation:, which will remove a single annotation, and removeAnnotations: which will remove an array of annotations. It also has an annotations property which lets you the current array of annotations. You should be able to select and remove the annotations that you want to remove and then add new ones to replace them.
I think you could try finding user location like this
let locationManager: CLLocationManager = CLLocationManager()
(write this as a class property, not inside any viewDidLoad!)
then u instantly have locationManager coordinates.
self.mapView.removeAnnotations(annotationsToRemove as [AnyObject])
could you print the "annotationsToRemove as [AnyObject]" and tell us what is the content ?
actually all this code is suspicious:
let annotationsToRemove = (self.mapView.annotations as NSArray).mutableCopy() as! NSMutableArray
annotationsToRemove.removeObject(self.mapView.userLocation)
annotationsToRemove.removeObjectsInArray(objects as [AnyObject])
self.mapView.removeAnnotations(annotationsToRemove as [AnyObject])
you define a constant, then edit it with removeObjects and then pass it to removeAnnotations ? strange man, please get as many prints on these lines as you can and tell what they are so we can help

Swift - fatal error: unexpectedly found nil while unwrapping an Optional value on MKCoordinateRegionMakeWithDistance

I'm trying to get my map to show directions to a local searched location from the current user location.
I'm getting an EXC_BAD_INSTRUCTION on the line:
let region = MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate, 2000, 2000)`
And on the line:
else {
self.showRoute(response)
}
I have a feeling the nil it's receiving is from the user location, which I'm not sure why it would be receiving a nil there.
Here is the full code for my view controller if needed:
class RouteViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var routeMap: MKMapView!
var destination = MKMapItem?()
override func viewDidLoad() {
super.viewDidLoad()
routeMap.showsUserLocation = true
routeMap.delegate = self
self.getDirections()
}
func getDirections() {
let request = MKDirectionsRequest()
request.setSource(MKMapItem.mapItemForCurrentLocation())
request.setDestination(destination!)
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler({(response:
MKDirectionsResponse!, error: NSError!) in
if error != nil {
println("Error getting directions")
} else {
self.showRoute(response)
}
})
}
func showRoute(response: MKDirectionsResponse) {
for route in response.routes as! [MKRoute] {
routeMap.addOverlay(route.polyline,
level: MKOverlayLevel.AboveRoads)
for step in route.steps {
println(step.instructions)
}
}
let userLocation = routeMap.userLocation
let region = MKCoordinateRegionMakeWithDistance(
userLocation.location.coordinate, 2000, 2000)
routeMap.setRegion(region, animated: true)
}
func mapView(mapView: MKMapView!, rendererForOverlay
overlay: MKOverlay!) -> MKOverlayRenderer! {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blueColor()
renderer.lineWidth = 5.0
return renderer
}
}
And the segue code:
override func prepareForSegue(segue: UIStoryboardSegue,
sender: AnyObject?) {
let routeViewController = segue.destinationViewController
as! RouteViewController
let indexPath = self.tableView.indexPathForSelectedRow()
let row = indexPath?.row
routeViewController.destination = mapItems[row!]
}
Any help would be appreciated, thanks!
The problem is this line:
let userLocation = routeMap.userLocation
The result, userLocation might be nil, and its location might be nil, because the map might not have been told to, or succeeded in acquiring, the user's location. You are not taking into account that possibility.
The way to do that is to unwrap the Optionals safely and proceed only if the unwrapping succeeded:
if let userLocation = routeMap.userLocation, loc = userLocation.location {
let region = MKCoordinateRegionMakeWithDistance(
loc.coordinate, 2000, 2000)
routeMap.setRegion(region, animated: true)
}
We don't need the userLocation separately for anything, so we can collapse that into a single test:
if let loc = routeMap.userLocation.location {
let region = MKCoordinateRegionMakeWithDistance(
loc.coordinate, 2000, 2000)
routeMap.setRegion(region, animated: true)
}

Resources