MKMapView doesn't show popup on pin when tapped - ios

I have a UIScrollView(gray) with a UIView (white) attached on. On the view I have attached an MKMapView with a pin inside.
For some unknown reason the pin doesn't show the popup when tapped.
Here some code:
UIView * whiteMapView = [[UIView alloc] initWithFrame:CGRectMake(x, y, w, h)];
whiteMapView.backgroundColor = [UIColor whiteColor];
whiteMapView.clipsToBounds = NO;
whiteMapView.userInteractionEnabled = YES;
[self.scrollView addSubview:whiteMapView];
x = 10.0f;
y = x;
w = CGRectGetWidth(whiteMapView.frame) - (x * 2);
h = w;
self.mapView = [[MKMapView alloc] initWithFrame:CGRectMake(x, y, w, h)];
self.mapView.delegate = self;
self.mapView.scrollEnabled = NO;
[whiteMapView addSubview:self.mapView];
[self.mapView removeAnnotations:self.mapView.annotations];
Shop * shop = [[Shop alloc] init];
shop.name = self.userInfo[#"shopName"];
shop.shopDescription = self.userInfo[#"goods_description"];
shop.latitude = self.userInfo[#"lat"];
shop.longitude = self.userInfo[#"lon"];
MapPin * pin = [[MapPin alloc] initWithShop:shop];
[self.mapView addAnnotation:pin];
Here the delegate method:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation
{
if (annotation == mapView.userLocation)
{
return nil;
}
else
{
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Pin"];
pinView.userInteractionEnabled = YES;
pinView.image = [UIImage imageNamed:#"pin_mappa_red"];
pinView.canShowCallout = YES;
pinView.animatesDrop = NO;
UIButton *disclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
disclosureButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
disclosureButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[disclosureButton addTarget:self action:#selector(didPressPin:) forControlEvents:UIControlEventTouchUpInside];
disclosureButton.tag = [[[(MapPin *)annotation shop] idshop] intValue];
pinView.rightCalloutAccessoryView = disclosureButton;
return pinView;
}
}
In another part of the app this code works perfectly.
Ideas ?

Try to change like this viewForAnnotation as follows
-(MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:
(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = nil;
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if(annotation)
{
UIButton *disclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
UIImageView *imageInMap = [[UIImageView alloc]initWithImage: [UIImage imageNamed:#"net.png"]];
[disclosureButton addTarget:self action:#selector(mapCallOutPressed) forControlEvents:UIControlEventTouchUpInside];
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[self.locationMapVIew dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.rightCalloutAccessoryView = disclosureButton;
pinView.leftCalloutAccessoryView = imageInMap;
pinView.leftCalloutAccessoryView.frame = CGRectMake(0, 0, 35, 35);
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
}
else {
[self.locationMapVIew.userLocation setTitle:#"I am here"];
}
return pinView;
}

Check this method is call or not
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSLog("Pin called");
}
If this method is not called then there may be any problem for mapview or Annotation.

Related

When tap on Annotation Map location is not zoomed

I used this one in the below delegates and set the image in annotation. When tapping the annotation its didselectannotation delegate is not called. But when I use the default then its working. Please suggest if anyone can help in this context.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
static NSString *defaultPinID = #"Annotation";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
UIImage *originalImage = [UIImage imageNamed:#"map.png"];
pinView.canShowCallout = YES;
pinView.image = [self drawImage:originalImage inRect:CGRectMake(0, 0, 106, 148)];
pinView.calloutOffset = CGPointMake(0, -5);
UIImageView *profileImageView = [[UIImageView alloc]init];
profileImageView.frame = CGRectMake(6, 7, 40, 40);
[profileImageView setImage:[UIImage imageNamed:#"user.png"]];
[profileImageView setBackgroundColor:[UIColor whiteColor]];
[self setRoundedAvatar:profileImageView toDiameter:40 atView:self.view];
[pinView addSubview:profileImageView];
I have done this using the gestureRecognizer to PinView.
UITapGestureRecognizer *tapLocation = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gestureRecognizerShouldBeginFocusMap:)];
tapLocation.numberOfTapsRequired=1;
[pinView addGestureRecognizer:tapLocation];
- (BOOL)gestureRecognizerShouldBeginFocusMap:(UIGestureRecognizer *)gestureRecognizer
{
MKMapRect visibleMapRect = self.mapView.visibleMapRect;
NSSet *visibleAnnotations = [self.mapView annotationsInMapRect:visibleMapRect];
for ( MyAnnotation *annotation in visibleAnnotations ){
[self setCenterCoordinate:annotation.coordinate zoomLevel:18 animated:YES];
}
return YES;
}

Map annotation swapping from displaying image to default pin randomly

When the map is tested through simulator I notice that some annotations display the default pin instead of the customized image. When I go back to the apps Home menu and enter the mapview again the same thing happens with different annotations.
This code present 4 annotations out of 20 that I have which all uses the same code.
-(void)viewDidLoad {
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
[mapView setDelegate:self];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
MKCoordinateRegion test1 = { {0.0, 0.0} , {0.0, 0.0} };
test1.center.latitude = 55.705609;
test1.center.longitude = 13.195707;
[mapView setRegion:test1 animated:YES];
testmap *ann2 = [[testmap alloc] init];
ann2.title = #"test1";
ann2.subtitle = #"Klicka här för mer info";
ann2.coordinate = test1.center;
ann2.name = #"test1";
[mapView addAnnotation:ann2];
MKCoordinateRegion test2 = { {0.0, 0.0} , {0.0, 0.0} }; //ändra ner
test2.center.latitude = 55.710113;
test2.center.longitude = 13.213500;
[mapView setRegion:test2 animated:YES];
testmap *ann3 = [[testmap alloc] init];
ann3.title = #"test2";
ann3.subtitle = #"Klicka här för mer info";
ann3.coordinate = test2.center;
ann3.name = #"test2";
[mapView addAnnotation:ann3];
MKCoordinateRegion test3 = { {0.0, 0.0} , {0.0, 0.0} };
test3.center.latitude = 55.708981;
test3.center.longitude = 13.197266;
[mapView setRegion:test3 animated:YES];
testmap *ann4 = [[testmap alloc] init];
ann4.title = #"test3";
ann4.subtitle = #"Klicka här för mer info";
ann4.coordinate = test3.center;
ann4.name = #"test3";
[mapView addAnnotation:ann4];
MKCoordinateRegion test4 = { {0.0, 0.0} , {0.0, 0.0} }; //ändra ner
test4.center.latitude = 55.705170;
test4.center.longitude = 13.191277;
[mapView setRegion:test4 animated:YES];
testmap *ann5 = [[testmap alloc] init];
ann5.title = #"test4";
ann5.subtitle = #"Klicka här för mer info";
ann5.coordinate = test4.center;
ann5.name = #"test4";
[mapView addAnnotation:ann5];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView)
return nil;
else
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier]; annotationView.canShowCallout = YES;
NSString* thisModelName = ((testmap*)annotation).name;
if ([thisModelName isEqualToString:#"test1"]) {
annotationView.image = [UIImage imageNamed:#"test1"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
annotationView.highlighted = YES;
return annotationView;
}
else if ([thisModelName isEqualToString:#"test2"])
{
annotationView.image = [UIImage imageNamed:#"test2"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
annotationView.highlighted = YES;
return annotationView;
}
else if ([thisModelName isEqualToString:#"test3"])
{
annotationView.image = [UIImage imageNamed:#"test3"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
annotationView.highlighted = YES;
return annotationView;
}
else if ([thisModelName isEqualToString:#"test4"])
{
annotationView.image = [UIImage imageNamed:#"test4"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
annotationView.highlighted = YES;
return annotationView;
}
}
return nil;
}
You're getting default pins "randomly" because of this code:
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (annotationView)
return nil;
What this code says is if the dequeueReusableAnnotationViewWithIdentifier: returns a view (ie. if annotationView is not nil), return nil from the delegate method.
When you return nil from the viewForAnnotation delegate method, the map view does the following:
If the annotation is of type MKUserLocation, it will display the default blue dot.
If the annotation is not an MKUserLocation, it will display the default red pin.
What you probably meant was:
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (annotationView)
return annotationView;
However, this will create a new problem because if the dequeue returns a view (a view that was previously used for a different annotation), the image of the dequeued view might not match the image that should be used for the current annotation.
So what will happen is annotation images will switch around "randomly" as you zoom and pan the map.
The proper approach in viewForAnnotation is to:
Get a reference to a view using dequeueReusableAnnotationViewWithIdentifier: and if that returns nil, create a new view. Set view properties that are common to all annotations only when creating a new view.
Using the view reference obtained in step 1, set view properties that are specific to the current annotation. If a dequeued view is being used, update its annotation property as well.
Example:
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
if (! [annotation isKindOfClass:[testmap class]])
{
//If annotation is NOT a "testmap" (eg. MKUserLocation),
//return nil so map view displays default view for it...
return nil;
}
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (! annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
//set view properties common to all annotations...
annotationView.canShowCallout = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//Do not use addTarget with a custom method for callout accessories.
//Instead, use the calloutAccessoryControlTapped delegate method shown below.
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.draggable = YES;
}
else {
//reusing a view, update its annotation to current...
annotationView.annotation = annotation;
}
//AFTER we have a view reference, set annotation-specific properties...
NSString* thisModelName = ((testmap*)annotation).name;
if ([thisModelName isEqualToString:#"test1"]) {
annotationView.image = [UIImage imageNamed:#"test1"];
}
else if ([thisModelName isEqualToString:#"test2"]) {
annotationView.image = [UIImage imageNamed:#"test2"];
}
else if ([thisModelName isEqualToString:#"test3"]) {
annotationView.image = [UIImage imageNamed:#"test3"];
}
else if ([thisModelName isEqualToString:#"test4"]) {
annotationView.image = [UIImage imageNamed:#"test4"];
}
/*
If image name will always be same as `name` property then
can use single line instead of if/else statements:
annotationView.image = [UIImage imageNamed:thisModelName];
*/
return annotationView;
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
if ([view.annotation isKindOfClass:[testmap class]]) {
testmap *tm = (testmap *)view.annotation;
NSLog(#"button for '%#' tapped", tm.name);
}
}

How to change the callout left accessory image view dynamically based on json response

I am trying to dynamically change the callout image based on json response.But only one image display for all callouts please help me how to do this
#pragma mark Map View Delegate Methods
method for view for annotation
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation
{
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"pin.png"];
pinView.frame = CGRectMake(0, 0, 25, 30);
pinView.calloutOffset = CGPointMake(0, 32);
// Add a detail disclosure button to the callout.
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = rightButton;
NSLog(#"JSON: %#", islandArray); // print
//to display a island image in callout view
UIImageView *calloutImage = [[UIImageView alloc] init];
NSLog(#"%#",[NSURL URLWithString:[[NSUserDefaults standardUserDefaults]objectForKey:#"mapImage"]]);
calloutImage.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[NSUserDefaults standardUserDefaults]objectForKey:#"mapImage"]]]];
calloutImage.frame = CGRectMake(10, 0, 30, 30);
[calloutImage.layer setCornerRadius:05.0f];
pinView.leftCalloutAccessoryView = calloutImage;
pinView.tintColor = MKPinAnnotationColorRed;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}

leftCalloutAccessoryView image reference?

Hello i'm building a mapbased App when i'm tapping on the Accessory i perform a segue to a profile page which gives information about the pin location. Now i have a image in my LeftCalloutAccesoryView which a i want to show on the detail page. Now i'm curious if there is a method to get the image which a set on LeftCalloutAccesoryView. I add the images dynamically.
my accessorycontroltapped code:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
companytitle = view.annotation.title;
description = view.annotation.subtitle;
thumbprofileimage = view.image;
//thumbprofileimage = [(UIImageView *)view.leftCalloutAccessoryView setImage:pin.image];
//UIImageView *leftIconView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
//leftIconView = [view.leftCalloutAccessoryView [[UIImageView alloc]];
//view.leftCalloutAccessoryView;
[self performSegueWithIdentifier:#"showPlattegrondDetails" sender:self];
}
my set pins code:
- (MKAnnotationView *)mapView:(MKMapView *)mpView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[RouteAnnotation class]]) {
MKPinAnnotationView *annotationView =
(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
leftIconView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[leftIconView setImage:pin.image];
annotationView.leftCalloutAccessoryView = leftIconView;
//annotationView.leftCalloutAccessoryView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView = rightButton;
return annotationView;
}
return nil;
}
Does someone have the solution of getting a reference to the image so i can send this image to the detail page?
You are already part way there with your mapView:annotationView:calloutAccessoryControlTapped: method.
Create a property to keep a reference to the image from the tapped callout:
#property (nonatomic, strong) UIImage *selectedCalloutImage;
And update the delegate method:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
companytitle = view.annotation.title;
description = view.annotation.subtitle;
thumbprofileimage = view.image;
//thumbprofileimage = [(UIImageView *)view.leftCalloutAccessoryView setImage:pin.image];
//UIImageView *leftIconView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
//leftIconView = [view.leftCalloutAccessoryView [[UIImageView alloc]];
//view.leftCalloutAccessoryView;
// Keep a reference to the callout's image
self.selectedCalloutImage = [(UIImageView *)view.leftCalloutAccessoryView image];
[self performSegueWithIdentifier:#"showPlattegrondDetails" sender:self];
}
Then pass the image to the subsequent controller in the prepareForSegue:sender: method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPlattegrondDetails"])
{
DetailViewController *controller = segue.destinationViewController;
controller.image = self.selectedCalloutImage;
}
}
You can then display / use it however you like.

callout is not showing by default in map

I am trying to show callout on a pin by without clicking on the pin.In short, I want show the callout when the pins are getting placed on the map.
This is code I am using:
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation // Method to handle all the annotations on map.
{
if([annotation isKindOfClass: [MKUserLocation class]])
return nil;
static NSString *annotationID = #"MyAnnotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationID] ;
if (!pinView) {
pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotationID];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"map_pin.png"];
//Setting Right call button
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//Setting Left Call button
self.favButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.favButton.frame = CGRectMake(0, 0, 23, 23);
self.favButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.favButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[self.favButton setImage:[UIImage imageNamed:#"favourite.png"] forState:UIControlStateNormal];
pinView.leftCalloutAccessoryView = self.favButton;
[self.mapView selectAnnotation:annotation animated:YES];
}
return pinView;
}
Any help would be appreciable.
Try with This :
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{
for (id<MKAnnotation> currentAnnotation in mapView.annotations) {
if ([currentAnnotation isEqual:annotationToSelect]) {
[mapView selectAnnotation:currentAnnotation animated:YES];
}
}
}
OR
EDIT :
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation // Method to handle all the annotations on map.
{
if([annotation isKindOfClass: [MKUserLocation class]])
return nil;
static NSString *annotationID = #"MyAnnotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationID] ;
if (!pinView) {
pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotationID];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"map_pin.png"];
//Setting Right call button
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//Setting Left Call button
self.favButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.favButton.frame = CGRectMake(0, 0, 23, 23);
self.favButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.favButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[self.favButton setImage:[UIImage imageNamed:#"favourite.png"] forState:UIControlStateNormal];
pinView.leftCalloutAccessoryView = self.favButton;
**[self performSelector:#selector(selectAnnotation:) withObject:annotation afterDelay:0.5];**
}
return pinView;
}
- (void)selectAnnotation:(id < MKAnnotation >)annotation
{
[self.mapView selectAnnotation:annotation animated:NO];
}

Resources