I have added this:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "id")
if let title = annotation.title{
if title! == "P"{
pinView.pinTintColor = UIColor.yellow
}
else{
pinView.pinTintColor = UIColor.gray
}
}
return pinView
}
But when I do this I can´t see my titles when I click on an annotation anymore, any ideas why?
You need to add the canShowCallout on your pinView. If the value of the canShowCallout property is true, a standard callout bubble is shown when the user taps a selected annotation view. The callout uses the title and subtitle text from the associated annotation object.
So just add the following row to your viewFor function and you´ll see the title.
pinView.canShowCallout = true
Related
In 2017 MKMarkerAnnotationView was announced to replace MKPinAnnotationView. As described by this WWDC video at 12:21, MKMarkerAnnotationView has three states:
Normal
Selected
Selected with Callout
How do you programmatically set the "Selected with Callout" state so that it displays as it does in the WWDC video? This seems like it should be a super straight forward thing to do, but I see absolutely nothing in the MapKit documentation, the only way I can get it to work reliably is this:
Documentation Links:
MKAnnotationView
MKMarkerAnnotationView
You can use canShowCallout property.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKMarkerAnnotationView
if pinView == nil {
pinView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
And you need to select the annotation to set the "Selected with Callout" state.
mapView.selectAnnotation(annotation, animated: true)
For some reason ever since I updated to iOS 11, my callout Accessory isn't being displayed for my annotations. I have a title and subtitle set up from data I query from my server, however I can't get the callout accessory along with the .detailedDisclosure to display.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
print("viewForannotation")
if annotation is MKUserLocation {
//return nil
return nil
}
// guard let annotation = annotation as? CalloutPin else { return nil }
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
//print("Pinview was nil")
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
}
let button = UIButton(type: UIButtonType.detailDisclosure) as UIButton // button with info sign in it
pinView!.canShowCallout = true
pinView!.rightCalloutAccessoryView = button
// pinView?.detailCalloutAccessoryView = button
return pinView
}
Does anyone have a solution for this? Any help would be much appreciated as I've been dealing with this problem for a long time now as I need the callout Accessory to display in order for me to segue to another view controller when my annotation pin is selected. Thanks!
Here's what's being displayed right now: MapView Annotation
I have a mapView with annotations displaying titles and subtitles. The subtitles are sometimes longer than the width of the annotation, so I am wondering if i can make them multiline?
It's coded like this so far:
func annotate(newCoordinate, title: String, subtitle: String) {
let annotation = MKPointAnnotation()
annotation.coordinate = newCoordinate
annotation.title = title
annotation.subtitle = subtitle
self.map.addAnnotation(annotation)
}
Then i have a few options set in
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {...}
which are not relevant here.
Is it posible to make a custom annotation view?
I've tried a couple of things, but nothing worked. The closest I can get is adding a button to display the longer subtitle separately, but i'd rather have it inside the annotation.
Is it possible?
I figured it out, I added a label in viewForAnnotation and it just worked
¯\_(ツ)_/¯
func mapView(mapView: MKMapView, viewForAnnotation 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.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
}
else {
pinView!.annotation = annotation
}
//THIS IS THE GOOD BIT
let subtitleView = UILabel()
subtitleView.font = subtitleView.font.fontWithSize(12)
subtitleView.numberOfLines = 0
subtitleView.text = annotation.subtitle!
pinView!.detailCalloutAccessoryView = subtitleView
return pinView
}
I currently have a custom MKAnnotationView set in a map callout, and it's working well. I however want to add a button to the callout view, but when i tap the button it closes the annotation view before it gets called. How can i get around this?
Here are pertinent bits of my code:
In my view for annotations:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "mapReuseId"
var mapView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if mapView == nil {
mapView = MKAnnotationView(annotation: annotation as! Annotation, reuseIdentifier: reuseId)
mapView!.canShowCallout = false
} else {
mapView!.annotation = annotation as! Annotation
}
mapDottView!.image = customImage
return mapDottView
}
In my didSelect delegate:
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
let callOut = customCallOutView(with: data)
view.addSubview(callOut)
// some layout here
}
The customCallOutView is longish, but the important part is that it has a UIButton which never gets called on tap. Any ideas?
You can try to put a delay when your button is tapped.
You can use Grand Central Dispatch or Perform Selector After Delay.
// Do what you need to do when your button was tapped.
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
// Dismiss your annotation.
}
Try the following code:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "mapReuseId"
var mapView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if mapView == nil {
mapView = MKAnnotationView(annotation: annotation as! Annotation, reuseIdentifier: reuseId)
mapView!.canShowCallout = true
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
} else {
mapView!.annotation = annotation as! Annotation
}
mapDottView!.image = customImage
return mapDottView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
print(#function)
// this method will be called when the button is tapped.
// annotation view doesn't disappear
}
I am using MKPinAnnotationView inside my App.
I am setting MapView object as delegate, and using this code for customising my AnnotationView
func mapView(mapView: MKMapView, viewForAnnotation 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.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
// pinView!.canShowCallout = true
pinView!.image = UIImage(named:"store.jpg")
pinView!.animatesDrop = true
pinView!.pinTintColor = UIColor.darkGrayColor()
}
else {
pinView!.annotation = annotation
}
return pinView
}
I am getting custom AnnotationView as I required.However, I am missing the features of title and subtitle of MKPointAnnotation.
I wish to see title and subtitle for the grey dots.
I was overriding one func
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
mapView.deselectAnnotation(view.annotation, animated: true)
}
I commented this function out and got the titles and subtitles.
Updated Code
/*
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
mapView.deselectAnnotation(view.annotation, animated: true)
}
*/
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView.canShowCallout = true
pinView.animatesDrop = true
pinView.pinTintColor = UIColor.darkGrayColor()
pinView.draggable = true
pinView.accessibilityLabel = "hello"
let btn = UIButton(type: .DetailDisclosure)
pinView.rightCalloutAccessoryView = btn
return pinView
}