Swift - MKPinAnnotation image issue - ios

I'm trying to change my pin annotation image to something other than the pin.
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!.animatesDrop = true
pinView!.pinColor = .Green
pinView!.image = UIImage(named: "icon1.png")
// Add image to left callout
var mugIconView = UIImageView(image: UIImage(named: "test.png"))
pinView!.leftCalloutAccessoryView = mugIconView
// Add detail button to right callout
var calloutButton = UIButton.buttonWithType(.DetailDisclosure) as UIButton
pinView!.rightCalloutAccessoryView = calloutButton
}
else {
pinView!.annotation = annotation
}
return pinView
Everything works except changing the pin image. I have a custom point annotation subclass which is this
I've been searching for hours but every other SO question I've found hasn't helped. I'd appreciate any help... thanks.
UPDATED WITH ANSWER
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
}
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("pin")
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
pinView!.canShowCallout = true
pinView!.image = UIImage(named: "test.png")
// Add image to left callout
var mugIconView = UIImageView(image: UIImage(named: "test.png"))
pinView!.leftCalloutAccessoryView = mugIconView
// Add detail button to right callout
var calloutButton = UIButton.buttonWithType(.DetailDisclosure) as UIButton
pinView!.rightCalloutAccessoryView = calloutButton
}
else {
pinView!.annotation = annotation
}
return pinView
}

You want MKAnnotationView, not MKPinAnnotationView. Pin annotations can't customize their image.
See this SO answer for additional details

Related

MKMarkerAnnotationView not showing callout

I am currently working on creating callouts for annotations I have added to my mapview via MapKit. The annotations work out well but currently callouts aren't being displayed even though I am using the right code to enable them (I believe).
HERE is my viewFor annotation code block.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if let annotation = annotation as? ClusterAnnotation {
let identifier = "cluster"
return mapView.annotationView(annotation: annotation, reuseIdentifier: identifier)
} else {
let identifier = "pin"
let annotationView = mapView.annotationView(of: MKMarkerAnnotationView.self, annotation: annotation, reuseIdentifier: identifier)
annotationView.isEnabled = true
annotationView.canShowCallout = true
annotationView.accessibilityLabel = "hi"
annotationView.isHidden = false
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView.markerTintColor = UIColor.customBlue()
annotationView.glyphImage = UIImage(named: "person")
return annotationView
}
}
Extension code block for annotationView function.
extension MKMapView {
func annotationView<T: MKAnnotationView>(of type: T.Type, annotation: MKAnnotation?, reuseIdentifier: String) -> T {
guard let annotationView = dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) as? T else {
return type.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
annotationView.annotation = annotation
return annotationView
}
}
The annotation enlarges as I select it, and in the didSelect code block it runs the print statement I run through it. Not exactly sure what is going on that's not allowing the callout to show even though I've literally enabled just about everything.
Please Used This Code.
This code working fine for me.
This Code support Swift4 and Swift5.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
if (annotation is MKUserLocation) {
return nil
} else {
let annotationIdentifier = "AnnotationIdentifier"
let nibName = "MyAnnotationView" //My XIB Name
let viewFromNib = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! MyAnnotationView // get My XIB
var annotationView: MyAnnotationView?
// if there is a view to be dequeued, use it for the annotation
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) as? MyAnnotationView {
if dequeuedAnnotationView.subviews.isEmpty {
dequeuedAnnotationView.addSubview(viewFromNib)
}
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
} else {
// if no views to dequeue, create an Annotation View
let av = MyAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.addSubview(viewFromNib)
annotationView = av // extend scope to be able to return at the end of the func
}
// after we manage to create or dequeue the av, configure it
if let annotationView = annotationView {
annotationView.canShowCallout = true // callout bubble
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView.frame = CGRect(x: 0, y: 0, width: 75, height: 80)
let customView = annotationView.subviews.first as! MyAnnotationView
customView.frame = annotationView.frame
}
return annotationView
}
}
This Code OutPut :
Happy To Help You.
From the source code documentation:
// If YES, a standard callout bubble will be shown when the annotation is selected.
// The annotation must have a title for the callout to be shown.
#property (nonatomic) BOOL canShowCallout;
Without the Title value being set the other items will not show up.

MKAnnotationView Callout Accessory is not getting displayed in iOS 11

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

Xamarin.iOS : How to change the annotation pin colour in apple maps

I want to change the colour of pin. Following is my code to add the pin on map. Thanks in advance. Any kind of help will be appreciated:
map.AddAnnotations(new MKPointAnnotation
{
Title = "Technician's Location",
Coordinate = new CLLocationCoordinate2D(lattitude, longitude)
});
You can use the pinColor property of MKPinAnnotationView.
This can be added in the delegate method func mapView(mapView: MKMapView!,
viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!
A typical example of what this method can hold is :-
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.animatesDrop = true
pinView!.pinColor = .Purple // you can change color here!
}
else {
pinView!.annotation = annotation
}
return pinView

Show Annotation Title and SubTitle in Custom MKPinAnnotationView

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
}

How can I show the iPhone Maps app blue dot with light blue field for current location instead of red pin? (in Swift)

So actually there was a similar question to mine and I found it here How to get iPhone Maps app blue dot with light blue field for current location? , I tried this solution but it didn't work, that's why it's time for my next question...
I have a map view in my ios swift app and I'm centering it on user's location. So far it works great but the location is marked with a red pin, and instead of that I want I want this typical apple blue dot with a field around it. My code is as follows:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
mapView.delegate = self
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let coordinateRegion = MKCoordinateRegionMakeWithDistance(appDelegate.getLocation().coordinate, 500, 500)
mapView.setRegion(coordinateRegion, animated: true)
mapView.showsUserLocation = true
print("MapEvents: \(appDelegate.getLatitude()), \(appDelegate.getLongitude())")
//this prints correct GPS coords
}
so what am I doing wrong?
==== EDIT
Following Ahmed's clue in the comment section - yes, I have this method implemented:
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
var reuseId = ""
if annotation.isKindOfClass(FBAnnotationCluster) {
reuseId = "Cluster"
var clusterView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
clusterView = FBAnnotationClusterView(annotation: annotation, reuseIdentifier: reuseId, options: nil)
return clusterView
} else {
reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.calloutOffset = CGPoint(x: -5, y: 5)
pinView!.canShowCallout = true
pinView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure) as UIView
return pinView
}
}
The reason for that is because I'm using marker clustering from this tutorial https://github.com/ribl/FBAnnotationClusteringSwift
when I commented out this method I see the blue dot, which is great, but now I need to bring the old code back - is there a way that I could use both functionalities (clustering and blue dot)? How should I modify my view for annotation method then?
Thanks a lot!
In the MKMapView viewForAnnotation delegate method, return nil if the annotation's type is MKUserLocation.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
var reuseId = ""
if annotation.isKindOfClass(FBAnnotationCluster) {
reuseId = "Cluster"
var clusterView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
clusterView = FBAnnotationClusterView(annotation: annotation, reuseIdentifier: reuseId, options: nil)
return clusterView
} else {
reuseId = "Pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.calloutOffset = CGPoint(x: -5, y: 5)
pinView!.canShowCallout = true
pinView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure) as UIView
return pinView
}
}

Resources