I'm displaying a few map pins on a map view. I can't figure out why the callout won't show when an annotation is touched. Here's my code. I have some conditional code in the viewDidLoad method to display a different pin image depending on a category id. The custom pins display correctly, but when you touch them nothing happens.
thanks for any help with this.
- (void)viewDidLoad {
[super viewDidLoad];
[self requestData];
CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(44.2632, 11.4403);
MKCoordinateSpan span;
span.latitudeDelta=5;
span.longitudeDelta=5;
MKCoordinateRegion ITRegion = MKCoordinateRegionMake(centerCoord, span);
ITRegion.span=span;
[mapView setRegion: ITRegion animated: YES];
mapView.delegate=self;
[self.mapView setShowsUserLocation:YES];
for (int i=0; i<[publicDataArray count]; i++) {
MKPointAnnotation* annotation= [MKPointAnnotation new];
CLLocationCoordinate2D coordinate;
coordinate.latitude = [[[[publicDataArray objectAtIndex:i] objectForKey:#"address"] objectForKey:#"lat"] doubleValue];
coordinate.longitude = [[[[publicDataArray objectAtIndex:i] objectForKey:#"address"] objectForKey:#"lng"] doubleValue];
NSString *catId = [NSString stringWithFormat:#"%#",[[publicDataArray objectAtIndex:i] objectForKey:#"category_id"]];
if ([catId isEqual: #"213"]) {
annView.image = [UIImage imageNamed:#"comprareMap.png"];//sets image for pin
} else if ([catId isEqual:#"217"]) {
annView.image = [UIImage imageNamed:#"vedereMap.png"];//sets image for pin
} else if ([catId isEqual:#"221"]) {
annView.image = [UIImage imageNamed:#"mangiareMap.png"];//sets image for pin
}
annotation.coordinate = coordinate;
[mapView addAnnotation: annotation];
}
}
- (MKAnnotationView *) mapView:(MKMapView *)mapingView viewForAnnotation:(id <MKAnnotation>) annotation {
annView = nil;
if(annotation != mapingView.userLocation)
{
static NSString *defaultPinID = #"";
annView = (MKAnnotationView *)[mapingView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( annView == nil )
annView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] ;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = rightButton;
annView.canShowCallout = YES;
}
return annView;
}
Related
for (int i = 0; i < self.businessArray.count; i++) {
Business *business = [self.businessArray objectAtIndex:i];
MapAnnotation *mapAnnotation = [[MapAnnotation alloc] init];
NSLog(#"%f %f", business.coordinate.latitude, business.coordinate.longitude);
mapAnnotation.title = business.name;
mapAnnotation.subtitle = business.address1;
mapAnnotation.coordinate = business.coordinate;
[bMapView addAnnotation:mapAnnotation];
NSLog(#"ti %#", mapAnnotation.title);
NSLog(#"sub %#", mapAnnotation.subtitle);
NSLog(#"coo %f %f", mapAnnotation.coordinate.latitude, mapAnnotation.coordinate.longitude);
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *pinView;
if (annotation != mapView.userLocation) {
static NSString *defauleID = #"myLocation";
// pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:defauleID];
if (pinView == nil) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier:defauleID];
}
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
}
return pinView;
}
error:
An instance 0x1cdd97b0 of class MapAnnotation was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
(
Context: 0x0, Property: 0x1cd97a30>
Release the annotation every time inside the loop
for (int i = 0; i < self.businessArray.count; i++) {
Business *business = [self.businessArray objectAtIndex:i];
MapAnnotation *mapAnnotation = [[MapAnnotation alloc] init];
NSLog(#"%f %f", business.coordinate.latitude, business.coordinate.longitude);
mapAnnotation.title = business.name;
mapAnnotation.subtitle = business.address1;
mapAnnotation.coordinate = business.coordinate;
NSLog(#"ti %#", mapAnnotation.title);
NSLog(#"sub %#", mapAnnotation.subtitle);
NSLog(#"coo %f %f", mapAnnotation.coordinate.latitude, mapAnnotation.coordinate.longitude);
[bMapView addAnnotation:mapAnnotation];
[mapAnnotation release];
}
i think you have receiving a notification by adding the observer.. and when you received that notification and execute the function associated with that observer deallocating your MapAnnotation but you are not removing that observer please remove observer too in dealloc...
[[NSNotificationCenter defaultSenter] removeObserver:self];
Hope this will help you..
Well, I have a view with a map where I load some annotations. Everything works fine, but when I want to erase those annotations and include other annotations they do not show up until I move (scroll) the map.
Any suggestion?
EDITED:
Seems like instead of using this:
[self updateMap];
I have to use:
[self performSelectorOnMainThread:#selector(updateMap) withObject:nil waitUntilDone:true];
Being update map the method where I add my new annotations.
Try smth like this:
[mapView removeAnnotations:[mapView annotations]];
NSArray *targetArray = /*YOUR ARRAY NAME with object, containing `latitude`, `longitude` and `title` values*/
for (id *item in targetArray) {
if (item.latitude && item.longitude) {
MKPin *pin = [[MKPin alloc] init]; // MKPin is your class which specifies the deledate `MKAnnotation`
pin.coordinate = CLLocationCoordinate2DMake(item.latitude, item.longitude);
pin.title = item.title;
[mapView addAnnotation:pin];
}
}
In the viewdidload use :
- (void)viewDidLoad
{
NSMutableArray* annotations=[[NSMutableArray alloc] init];
MyAnnotation* myAnnotation = [[MyAnnotation alloc] init];
myAnnotation.coordinate = theCoordinate;
[annotations addObject:myAnnotation];
MKMapRect flyTo = MKMapRectNull;
for (id <MKAnnotation> annotation in annotations)
{
NSLog(#"fly to on");
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
if (MKMapRectIsNull(flyTo))
{
flyTo = pointRect;
}
else
{
flyTo = MKMapRectUnion(flyTo, pointRect);
//NSLog(#"else-%#",annotationPoint.x);
}
}
// Position the map so that all overlays and annotations are visible on screen.
mapView.visibleMapRect = flyTo;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"welcome into the map view annotation");
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// try to dequeue an existing pin view first
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop=YES;
pinView.canShowCallout=YES;
pinView.draggable = NO;
pinView.pinColor=MKPinAnnotationColorGreen;
//button on the right for popup for pins
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
//zoom button on the left of popup for pins
UIButton* leftButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
[leftButton setTitle:annotation.title forState:UIControlStateNormal];
[leftButton addTarget:self
action:#selector(zoomToLocation:) forControlEvents:UIControlEventTouchUpInside];
pinView.leftCalloutAccessoryView = leftButton;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"profile.png"]];
pinView.leftCalloutAccessoryView = profileIconView;
[profileIconView release];
return pinView;
}
Hopefully this helps !!!!!!!!!
I am trying for a custom callout for a pin dropped in a mapView .. I am able to do this by hiding the default callout of pinView and showing my custom call out there. ().. everything is working fine ... But only prob is i am not able to assign the correct information for the call out ..I had shown the Default call out in which info is different than my custom call out. I ve attached the scrren shot .....
Here is my code
-(void)mapViewImplementaion
{
[mapview setMapType:MKMapTypeStandard];
mapview.showsUserLocation=YES;
for (int i =0;i<[allResultsArr count];i++)
{
List_Map_details *object=[allResultsArr objectAtIndex:i];
CLLocationCoordinate2D coordinat = {[object.lati floatValue], [object.longi floatValue]};
[mapview setRegion:MKCoordinateRegionMake(coordinat,
MKCoordinateSpanMake(0.027f, 0.027f))];
DisplayMapPark *ann = [[DisplayMapPark alloc] init];
ann.title =[NSString stringWithFormat:#"%#",object.forRetailerName];
ann.subtitle=[NSString stringWithFormat:#"%# %# %#",object.forAddress,object.forZipCode,object.forCityName];
ann.latitude=[object.lati floatValue];
ann.longitude=[object.longi floatValue];
ann.coordinate = coordinat;
[mapview addAnnotation:ann];
[ann release];
}
CalloutMapAnnotationView *calloutMapAnnotationView;
int m=1;
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView *pinView = nil;
// here i wrote some code for my custom callout to generate(not shown)
if(annotation != mapview.userLocation)
{
//int i=0;
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapview dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
NSString *imagName = [NSString stringWithFormat:#"%d.png", m];
UIImage *image = [UIImage imageNamed:imagName];
[pinView setImage:image];
pinView.canShowCallout = NO;
// To show this in scrren Shot i set it to Yes;
[pinView setAnnotation:annotation];
pinView.tag=m;
UIButton *rightButton=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView=rightButton;
//pinView.rightCalloutAccessoryView.frame=CGRectMake(0, 0, 60, 60);
m++;
}
else
{
[mapview.userLocation setTitle:#"Ik ben hier"];
}
pinView.annotation = annotation;
[rightButton release];
return pinView;
}
Hi if any one is awre of this .. please help !!!!!
I solved this issue. It was the mistake by me. I was just not assigning the tags to the pins properly .. and when the user selects the pin i was reading some other pin's information.... Thanks all
I am a newbie in MapKit for iPhone and tried to implement this, for some reason I can't see the current location blue dot, anyone else had this issue????
#import "DetailMapViewController.h"
#import "mapAnnotations.h"
#implementation DetailMapViewController
#synthesize inStock;
-(void)getlocation:(CLLocationCoordinate2D)loc
{
location = loc;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"Street View";
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.delegate=self;
//MKCoordinateRegion region;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(location, 5000, 5000);
mapAnnotations *ann = [[mapAnnotations alloc] init];
ann.title = #"";
ann.subtitle = #"";
ann.coordinate = region.center;
mapView.showsUserLocation = YES;
[mapView addAnnotation:ann];
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
[self.view insertSubview:mapView atIndex:0];
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
if (annotation == mapView.userLocation)
{
annView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"blueDot"];
if (annView != nil)
{
annView.annotation = annotation;
}
else
{
annView = [[[NSClassFromString(#"MKUserLocationView") alloc] initWithAnnotation:annotation reuseIdentifier:#"blueDot"] autorelease];
}
}
if([inStock isEqual:#"yes"]){
annView.pinColor = MKPinAnnotationColorGreen;
}
if([inStock isEqual:#"no"]){
annView.pinColor = MKPinAnnotationColorRed;
}
if([inStock isEqual:#"unknown"]){
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"greyPin.png"]];
[annView addSubview:imageView];
}
annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
- (void)dealloc {
[super dealloc];
}
#end
The way the viewForAnnotation is currently written, it should actually crash when trying to show the current location because the "blue dot" annotation view doesn't have the pinColor or animatesDrop properties.
Try changing it to the following:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
if ([annotation isKindOfClass:MKUserLocation.class]) {
//user location view is being requested,
//return nil so it uses the default which is a blue dot...
return nil;
}
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
if([inStock isEqual:#"yes"]){
annView.pinColor = MKPinAnnotationColorGreen;
}
if([inStock isEqual:#"no"]){
annView.pinColor = MKPinAnnotationColorRed;
}
if([inStock isEqual:#"unknown"]){
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"greyPin.png"]];
[annView addSubview:imageView];
}
annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
On the simulator, the user's location will be Cupertino, CA, USA (a little south of San Francisco). If your own annotation is not within 5000 meters of that, you won't see the blue dot. You'll have to zoom out to see it.
self.mapView.showsUserLocation = YES;
I am annotating my map and setting an image just fine, but when I tap the annotation on the MapView, the image goes from my custom image back to the red pin. Why is this?
- (MKAnnotationView *)mapView:(MKMapView *)newMapView viewForAnnotation:(id )newAnnotation {
MKPinAnnotationView *annotation = [[MKPinAnnotationView alloc] initWithAnnotation:newAnnotation reuseIdentifier:#"currentloc"];
if (annotation == nil) {
annotation = [[MKAnnotationView alloc] initWithAnnotation:newAnnotation reuseIdentifier:#"currentloc"];
}
annotation.image = [UIImage imageNamed:#"anno.png"];
annotation.canShowCallout = YES;
annotation.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bus_stop_30x30.png"]];
annotation.leftCalloutAccessoryView = imgView;
return annotation;
}
My code looks identical to some sample code that does not produce this problem.
Answering my own question here, just in case others have the same issue. Notice that I am using "MKPinAnnotationView" - it should be changed to "MKAnnotationView" and everything works.
Fixed code:
- (MKAnnotationView *)mapView:(MKMapView *)newMapView viewForAnnotation:(id )newAnnotation {
MKAnnotationView *annotation = [[MKAnnotationView alloc] initWithAnnotation:newAnnotation reuseIdentifier:#"currentloc"];
if (annotation == nil) {
annotation = [[MKAnnotationView alloc] initWithAnnotation:newAnnotation reuseIdentifier:#"currentloc"];
}
annotation.image = [UIImage imageNamed:#"anno.png"];
annotation.canShowCallout = YES;
annotation.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bus_stop_30x30.png"]];
annotation.leftCalloutAccessoryView = imgView;
return annotation;
}
I think this is one of the best ways:
(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
NSLog(#"welcome into the map view annotation");
MyAnnotation* myAnnotation1=annotation;
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if([mapView isEqual:mapMainView]== NO)
{
return nil;
}
// try to dequeue an existing pin view first
// if ([annotation isKindOfClass:[myAnnotation1 class]])
// {
// try to dequeue an existing pin view first
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (nil == pinView)
{
MKAnnotationView* annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier] autorelease];
// annotationView.canShowCallout = YES;
// pinView.animatesDrop=YES;
//pinView.pinColor=MKPinAnnotationColorPurple;
//image
UIImage* flagImage = [UIImage imageNamed:#"map_marker_over2.png"];
CGRect resizeRect;
resizeRect.size = flagImage.size;
CGSize maxSize = CGRectInset(self.view.bounds,
[MapPropertyViewController annotationPadding],
[MapPropertyViewController annotationPadding]).size;
maxSize.height -= self.navigationController.navigationBar.frame.size.height + [MapPropertyViewController calloutHeight];
if (resizeRect.size.width > maxSize.width)
resizeRect.size = CGSizeMake(maxSize.width, resizeRect.size.height / resizeRect.size.width * maxSize.width);
if (resizeRect.size.height > maxSize.height)
resizeRect.size = CGSizeMake(resizeRect.size.width / resizeRect.size.height * maxSize.height, maxSize.height);
resizeRect.origin = (CGPoint){0.0f, 0.0f};
UIGraphicsBeginImageContext(resizeRect.size);
[flagImage drawInRect:resizeRect];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
annotationView.image = resizedImage;
annotationView.opaque = NO;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
rightButton.tag = myAnnotation1.tagAnnotation;
annotationView.rightCalloutAccessoryView = rightButton;
profileIconView = [[UIImageView alloc]initWithFrame:CGRectMake(18.5f, 10.0f, 37.0f, 30.0f)];
annotationView.leftCalloutAccessoryView = profileIconView;
//image
img = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString:[arrImages objectAtIndex:myAnnotation1.tagAnnotation]]]];
NSLog(#"Annotation Click %d",[arrImages count]);
NSLog(#"image %#",img);
profileIconView.image=img;
[profileIconView release];
[annotationView setEnabled:YES];
[annotationView setCanShowCallout:YES];
return annotationView;
}
return pinView;
// }
// return nil;
}
Try this if you want to set both Source to Destination pin images different.
MKPointAnnotation * sourceAnno= [[MKPointAnnotation alloc] init];
sourceAnno.coordinate=CLLocationCoordinate2DMake(YourSourcelatitude,YourSourcelongitude);
[sourceAnno setAccessibilityLabel:#“Source”];
sourceAnno.title = #“You”;
[mapview addAnnotation: sourceAnno];
DestinationAnno = [[MKPointAnnotation alloc] init];
DestinationAnno.coordinate = CLLocationCoordinate2DMake(YourDestinationlatitude,YourDestinationlongitude);
[DestinationAnno setAccessibilityLabel:#“Destination”];
DestinationAnno.title =#“Destination”;
[mapview addAnnotation: DestinationAnno];
In Delegate Method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPointAnnotation *PointAnno=(MKPointAnnotation *)annotation;
NSString * kPinAnnotationIdentifier = PointAnno.accessibilityLabel;
MKAnnotationView *AnnotationView = [[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:kPinAnnotationIdentifier];
if ([kPinAnnotationIdentifier isEqualToString:#"Source"])
{
AnnotationView.centerOffset = CGPointMake(8, -14);
AnnotationView.calloutOffset = CGPointMake(-8, 0);
AnnotationView.image = [UIImage imageNamed:#"pin_blue.png"];
AnnotationView.canShowCallout = YES;
}
else if([kPinAnnotationIdentifier isEqualToString:#"Destination"])
{
AnnotationView.centerOffset = CGPointMake(8, -14);
AnnotationView.calloutOffset = CGPointMake(-8, 0);
AnnotationView.image = [UIImage imageNamed:#"pin_red.png"];
AnnotationView.canShowCallout = YES;
}
return AnnotationView;
}
Thank you