MKMapView: Instead of Annotation Pin, a custom view - ios

I want to display an image in my MKMapView instead of little rock pin.
Can someone please put some helpful code here, or tell the way how to do it?
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:
(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:#"pinks.jpg"]; //as suggested by Squatch
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
I am expecting my image pinks.jpg to be on the map, pinning the location instead of default pin view (rock pin shaped). But still I am getting the default image of the pin.

When you want to use your own image for an annotation view, you should create an MKAnnotationView instead of an MKPinAnnotationView.
MKPinAnnotationView is a subclass of MKAnnotationView so it has an image property but it generally overrides that and draws a pin image (that's what it's for).
So change the code to:
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
//pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
//pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:#"pinks.jpg"]; //as suggested by Squatch
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
Notice that animatesDrop is also commented out since that property only exists in MKPinAnnotationView.
If you still want your image annotations to drop, you'll have to do the animation yourself. You can search Stack Overflow for "animatesdrop mkannotationview" and you'll find several answers. Here are the first two:
Is it possible to call animatesDrop in a MKAnnotationView rather than MKPinAnnotationView?
How can I create a custom "pin-drop" animation using MKAnnotationView?

Here's an answer on Swift 3. It dequeues annotation view if possible or creates a new one if not:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !(annotation is MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}
Swift 2.2:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}

I agree with with answer of the Anna and i like to show how will look that in swift3.This answer it's with many other options.Like a resize the image, get a list of images from array and ect.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? PetrolStation {
let identifier = "pinAnnotation"
var view: MKAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
as? MKPinAnnotationView { // 2
dequeuedView.annotation = annotation
view = dequeuedView
} else {
// 3
view = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
//here We put a coordinates where we like to show bubble with text information up on the pin image
view.calloutOffset = CGPoint(x: -7, y: 7)
//Here this is a array of images
let pinImage = PetrolItem[activePlace].imgPetrol?[activePlace]
//Here we set the resize of the image
let size = CGSize(width: 30, height: 30)
UIGraphicsBeginImageContext(size)
pinImage?.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let resizeImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
view.image = resizeImage
//Here we like to put into bubble window a singe for detail Informations
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
//Here we make change of standard pin image with our image
view.image = resizeImage
}
return view
}
return nil
}

Related

how to change default image in MKUserLocation annotation in Swift iOS

I have a map view in my app that displays the user's location. when the user's location is tapped an image is displayed as below:
is there a way to make this image customized to my liking, so for instance I would like to show the photo that the user has in his own profile, or any other static image that I would like to add.
similar to how the apple maps would show your profile picture in your location dot.
how can I do that here?
here is my code:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
print("user location image tapped")
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true
pinView?.canShowCallout = true
pinView?.isDraggable = true
// pinView?.pinColor = .purple
let rightButton: AnyObject! = UIButton(type: UIButton.ButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
any help on this? thank you.
let imageView = UIImageView(frame: CGRect(0, 0, 25, 25))
imageView.image = UIImage(named: "userpic");
imageView.layer.cornerRadius = imageView.layer.frame.size.width / 2
imageView.layer.masksToBounds = true
anotationView.frame = imageView.frame

Swift Annotation Custom Image

I'm using Swift 3 and Xcode 10 beta 3 and I need to use a custom image for my pins on the map. After the help of a guy on another post we made this code, it's all working except the pins are still the default.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? Annotation {
let identifier = "identifier"
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.image = annotation.image //add this
annotationView.canShowCallout = true
annotationView.calloutOffset = CGPoint(x: -5, y: 5)
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
return annotationView
}
return nil
}
let marker = Annotation(title: "LVR" , subtitle: "" , coordinate: CLLocationCoordinate2D(latitude: 43.772523, longitude: 11.254356))
marker.image = UIImage(named: "antonioli.png")
//mapView.addAnnotation(marker)
self.map.addAnnotation(marker)
The PNG file is in the main folder of my project like this:
How should I handle this problem?
Here MyAnnotation is a subclass of NSObject, MKAnnotation
func mapView(_ mapView: MKMapView,viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MyAnnotation == false
{
return nil
}
let senderAnnotation = annotation as! MyAnnotation
let pinReusableIdentifier = senderAnnotation.pinColor.rawValue
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: pinReusableIdentifier)
if annotationView == nil
{
annotationView = MKAnnotationView(annotation: senderAnnotation, reuseIdentifier: pinReusableIdentifier)
annotationView!.canShowCallout = true
}
let pinImage = UIImage(named:"location_curr.png")
annotationView!.image = pinImage
return annotationView
}
See Demo MapCustomImage

Changing MKMapView User Location Annotation

I'm attempting to change the user default location annotation on the MKMapView from the blue to a custom image named geo. It's hitting the line to set it to geo when I set breakpoints, but both points (the user default, and Passenger point are default red pinpoint annotations) Am I setting this wrong, or is there certain image stipulations?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKindOfClass(PassengerLocation) == false {
//User location
let userIdentifier = "UserLocation"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(userIdentifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:userIdentifier)
}
annotationView!.annotation = annotation
annotationView!.canShowCallout = true
// THIS IS NOT WORKING, DEFAULT RED PIN POINT STILL SHOWING
annotationView!.image = UIImage(named: "geo")
return annotationView
}
let identifier = "PassengerLocation"
if let annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView.enabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .DetailDisclosure)
annotationView.rightCalloutAccessoryView = btn
return annotationView
}
}
This works:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isEqual(mapView.userLocation) {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "userLocation")
annotationView.image = UIImage(named: "geo")
return annotationView
}
}
its working for me
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
// want to show a custom image if the annotation is the user's location.
guard !annotation.isKindOfClass(MKUserLocation) else {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "userLocation")
annotationView.image = UIImage(named: "icon_coordinates_self")
return annotationView
//return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "Annotation_map")
}
return annotationView
}
Use a regular MKAnnotationView if you want to customize the image. With a pin, all you can do is change the color.
guard !annotation.isKind(of: MKUserLocation.self) else {
return nil
}
That works perfectly

MKPinAnnotationView doesn't set custom image

I have to set custom image for different pins. With my code I'm able to set custom color for each of them but when I try to set custom image instead of colors, it doesn't work.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(MyAnnotation *)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyAnnotation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.myMap dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
NSString *stringType = [NSString stringWithFormat:#"%#", [(MyAnnotation *)annotationView.annotation stringType]];
if ([stringType isEqualToString:#"0"]) {
annotationView.image = [UIImage imageNamed:#"IconUserCerco.png"];
//annotationView.pinColor = MKPinAnnotationColorGreen;
} else if ([stringType isEqualToString:#"1"]) {
annotationView.image = [UIImage imageNamed:#"IconUserDefault.png"];
//annotationView.pinColor = MKPinAnnotationColorPurple;
} else if ([stringType isEqualToString:#"2"]) {
annotationView.image = [UIImage imageNamed:#"PinUniversity.png"];
//annotationView.pinColor = MKPinAnnotationColorRed;
}
return annotationView;
}
return nil;
}
Any help will be much appreciated. Thanks in advance.
Instead of MKPinAnnotationView can you use MKAnnotationView? You'll have to use following instead of MKPinAnnotationView
MKAnnotationView *annotationView = [self.myMap dequeueReusableAnnotationViewWithIdentifier:identifier];
iOS 9.0 onwards its recommended to use MKAnnotationView. That should solve your problem.
This is what it looks like in iOS 11.x Swift 4, note this won't work if you make the same mistake as me using MKPinAnnotationView. This will make a pin and you won't be able to change the image behind it.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pav:MKAnnotationView?
if (pav == nil)
{
pav = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pav?.isDraggable = true
pav?.canShowCallout = true
pav?.image = UIImage(named: "WIP.png")
pav?.calloutOffset = CGPoint(x: -8, y: 0)
pav?.autoresizesSubviews = true
// pav?.rightCalloutAccessoryView = UIButton(type: .roundedRect)
pav?.leftCalloutAccessoryView = UIButton(type: .contactAdd)
}
else
{
pav?.annotation = annotation;
}
return pav;
}

change image pin maps

What should I write in order to put a personal picture instead of the traditional red pin?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annView : MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "currentloc")
annView.pinTintColor = UIColor.redColor()
annView.animatesDrop = true
annView.canShowCallout = true
annView.calloutOffset = CGPointMake(-8, 0)
annView.autoresizesSubviews = true
annView.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
return annView
}
Use MKAnnotationView instead of MKPinAnnotationView, and then set its image property. I'd also suggest implementing the dequeue logic so that annotations can be reused:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annotationIdentifier = "SomeCustomIdentifier" // use something unique that functionally identifies the type of pin
var annotationView: MKAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if annotationView != nil {
annotationView.annotation = annotation
} else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView.image = UIImage(named: "annotation.png")
annotationView.canShowCallout = true
annotationView.calloutOffset = CGPointMake(-8, 0)
annotationView.autoresizesSubviews = true
annotationView.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
}
return annotationView
}

Resources