UIButton, Mapbox, Open new View programmatically - ios

I am a beginner, and i can't understand one thing.
In this example there exist Info button. As I understand there piece of code returns this button:
func mapView(_ mapView: MGLMapView, rightCalloutAccessoryViewFor annotation: MGLAnnotation) -> UIView? {
return UIButton(type: .detailDisclosure)
}
So the question is: how can I open another View (view name: extraInfo, viewcontroller's name: extraInfoController) from this button programmatically?
Please, can u reply in detail, because as i already sad, I am beginner. :)
(I am using Swift, not Obj-C)

You can use this delegate method
func mapView(_ mapView: MGLMapView, annotation: MGLAnnotation, calloutAccessoryControlTapped control: UIControl) {
}

Related

How to zoom, in MGL mapView, so that the view encompasses one "object" on the map

I have an MGLPolyline on a mapbox map and want to make is so when the user taps on the line it centers around the line and zooms in as much as possible so that the full line is on display. Currently, I make the centering work well but the zoom works randomly:
I just set it to max zoom, However, this is of course not what I want.
Bellow is where I want to add the zoom amount:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
print("Tapped")
mapView.setCenter(CLLocationCoordinate2D(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude), zoomLevel: mapView.zoomLevel, animated: true)
mapView.deselectAnnotation(annotation, animated: false)
}
MGLMapView actually has a baked in method specifically for this purpose. You should be able to implement the functionality using -showAnnotations:animated. If you want to fiddle around with the padding around your polyline, you can also use the showAnnotations:edgePadding:animated flavor of the method.
This would look like the following:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
mapView.showAnnotations(pointAnnotations, animated: true)
}

How can I change mapbox annotation view?

I've add several annotations with custom annotation view, but I have a reference only to the marker and not to the annotation view itself. So how can I change the annotation view elements?
You should store the annotations in a variable and when you want to change their views just remove them from the map with mapView.removeAnnotation(...) and add it back again with mapView.addAnnotation(...).
The method
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
}
will be called and you should return your changed view.
Pay attention to the fact that for performance reasons you should not use addAnnotation() or removeAnnotation() if you have a lot of annotations, but instead addAnnotations() and removeAnnotations()
I added all my annotation views to a dictionary
I created a global dictionary variable
var annotationViews = [CustomAnnotation:CustomAnnotationView]()
Then after creating each annotation view within my delegate function
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView?
I added it into my dictionary
let annotationView = MyAnnotationView(reuseIdentifier: rid, size: CGSize(width: 45, height: 45), annotation: annotation)
annotationViews[annotation as! MyAnnotation] = annotationView
Later when I wanted to change the text of a text view within my annotation view, I used my annotation in the dictionary call. This returned the annotation view that corresponded to it.
self.annotationViews[anno]?.textView.text = "My new text view status"
No deleting and re-adding required.
You could probably insert something smaller as the key for the dictionary, like annotation.uid or annotation.name or something. I just used the whole annotation object though

Can't select MKViewAnnotation twice?

I've got pins placed on a map and when I tap on them I'm calling the didSelect. The function only gets called the first time the pin is tapped, and after that it's not called on that same pin again unless I select another pin and then come back and tap it.
What that sounds like to me is the pin is being selected, and didSelect can only be called in unselected pins, so when I go tap on another pin it's deselecting the first pin and making it tappable again.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
view.isSelected = false
}
I don't understand why the above code does not work.
How can I allow my annotations be tapped more than one time in a row?
Try with this method deselectAnnotation
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
//do what you need here
mapView.deselectAnnotation(view.annotation, animated: true)
}
Hope this helps
There is another option, and that is to add a Gesture Recognizer for on the annotationView.
This will enable showing the callout view (since de-selecting the annotation immediately will not show it).
internal func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(mapPinTapGestureRecognizer)))
}
#objc private func mapPinTapGestureRecognizer(gestureRecognizer: UITapGestureRecognizer) {
// Will get called on the second time the pin is selected.
// And then, after that, it will be called every time.
}
Just don't forget to remove the recognizer when the annotation is no longer selected.
internal func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
// Remove the gesture recognizer when the annotation is no longer selected.
}

How to make a MGLPolyline tapable?

I am currently looking for a way to make a route (MGPLPolyline) tappable such that a user can choose between two possible routes under Mapbox. Unfortunately the route annotation doesn't seem to be tappable at all:
While i have properly set my MGLMapViewDelegate this method:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation)
is never invoked.
What did i miss knowing that each line inherited from MGLPolyline which is a subclass of an MGLAnnotation (which i was expected to be tappable...).
The Mapbox iOS API doesn't support that yet, unfortunately. See here.
There are a couple of workarounds within that link that you could try though.
UPDATE:
This is now possible: Check here.
You could do the following:
First, when you create the polyline do the following:
let polyline = CustomPolyline(coordinates: &coordinates, count: UInt(coordinates.count))
polyline.title = "" //It does not seem to matter what you set it to.
polyline.color = .darkGray
Then in the following method return false:
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
// Always allow callouts to popup when annotations are tapped.
print("ran?")
return false
}

Tap gesture for MapKit

Currently I have a map that has several Annotations.
For the Annotations I have
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView){
// Do your annotation click work
}
Is it possible to do this for tapping the Map only and not the Annotation and how can I do it?
In ViewWillAppear method :
let gestureRecognizer = UITapGestureRecognizer(target: self, action:"triggerTouchAction:")
mapView.addGestureRecognizer(gestureRecognizer)
And Whatever information you want to show just add code in following method :
func triggerTouchAction(gestureReconizer: UITapGestureRecognizer) {
//Add alert to show it works
}
Hope it going to help you to resolve issue.

Resources