1

I have the following code that gives me an EXC_BAD_ACCESS.

I have a map and I'm loading a circle image that represents the actual position in the map.

Edit here is the full code

#import "ComoLlegarViewController.h"
#import "MBProgressHUD.h"

/*#define COLOR_TEXTO_NORMAL          [UIColor colorWithRed:204.0f/255.0f green:204.0f/255.0f blue:204.0f/255.0f alpha:1.0f]*/
#define COLOR_TEXTO_NORMAL [UIColor darkGrayColor]
#define COLOR_TEXTO_SELECCIONADO    [UIColor colorWithRed:0.0f/255.0f green:10.0f/255.0f blue:100.0f/255.0f alpha:1.0f]


#define kTIENDA_UNAM_LATITUD    19.321066
#define kTIENDA_UNAM_LONGITUD   -99.176202

@interface ComoLlegarViewController ()

@property (strong, nonatomic) MKPointAnnotation *puntoTiendaUNAM;

// Metodo que crea un punto en el Mapa y apunta a la Tienda UNAM
- (void)dropPinUbicacionTiendaUNAM;
- (void)hacerZoomAlMapa;
@end


@implementation ComoLlegarViewController

@synthesize segmentedControl = _segmentedControl;
@synthesize mapa = _mapa;
@synthesize puntoTiendaUNAM = _puntoTiendaUNAM;

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
}

#pragma mark - View lifecycle

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self) {

        [self.navigationController.tabBarItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:COLOR_TEXTO_NORMAL, NSForegroundColorAttributeName, nil] forState:UIControlStateNormal];

        [self.navigationController.tabBarItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:COLOR_TEXTO_SELECCIONADO, NSForegroundColorAttributeName, nil] forState:UIControlStateSelected];


        [self.navigationController.tabBarItem setSelectedImage:[[UIImage imageNamed:@"icono_mapas_activado.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];

    }
    return self;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];

    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor blackColor], NSForegroundColorAttributeName,
                                [UIColor grayColor], NSForegroundColorAttributeName,
                                [NSNumber numberWithFloat:0.1f], NSShadowAttributeName,
                                nil];

    [_segmentedControl setTitleTextAttributes:attributes forState:UIControlStateNormal];

    // No need to retain (just a local variable)
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Localizando";
    hud.detailsLabelText = @"Tienda UNAM";
    [hud hide:YES afterDelay:0.7f];

    // localizamos el pin en el mapa en el background
    [self dropPinUbicacionTiendaUNAM];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidUnload
{
    [super viewDidUnload];

    _mapa = nil;
    _segmentedControl = nil;
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


/**
 Metodo que se encarga de mostrar el pin en el mapa con la ubicacion de la tienda UNAM
 */

- (void)dropPinUbicacionTiendaUNAM
{    
    // Referencia al mapa de la clase
    MKMapView *myMapView = _mapa;

    // Creamos un pin
    if (! _puntoTiendaUNAM) {
        _puntoTiendaUNAM= [[MKPointAnnotation alloc] init];
    }

    _puntoTiendaUNAM.title = @"TU Tienda UNAM";
    _puntoTiendaUNAM.coordinate = CLLocationCoordinate2DMake(kTIENDA_UNAM_LATITUD, kTIENDA_UNAM_LONGITUD);
    _puntoTiendaUNAM.subtitle = @"Dalias s/n, Oxtopulco, 04510 Coyoacán";

    // Lo agregamos al mapa
    [myMapView addAnnotation:_puntoTiendaUNAM];
    [myMapView setCenterCoordinate:_puntoTiendaUNAM.coordinate animated:YES];

    // Zoom al mapa para mostrar solo la region donde esta el pin, con un span de 1000 mts de radio
    MKCoordinateRegion mapRegion;
    mapRegion.center = _puntoTiendaUNAM.coordinate;
    mapRegion.span = MKCoordinateSpanMake(0.01, 0.01);
    [myMapView setRegion:mapRegion animated: YES];
}

#pragma mark MKMapView Delegate

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    // Creamos la vista de punto a desplegar
    MKPinAnnotationView *pinView = nil;
    pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pinTiendaUNAM"];

    if (! pinView) {

        pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pinTiendaUNAM"];

        // Configuramos la vista del punto

        UIImage *img=[UIImage imageNamed:@"bolita_mapa.png"];

        UIImageView *pinImageView = [[UIImageView alloc] initWithImage:img];
        [pinImageView setUserInteractionEnabled:YES];

        // Agregamos un gesture Recognizer a la bolita
        UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hacerZoomAlMapa)];
        [tapGestureRecognizer setNumberOfTapsRequired:1];
        [tapGestureRecognizer setNumberOfTouchesRequired:1];
        [pinImageView addGestureRecognizer:tapGestureRecognizer];

        [pinView addSubview:pinImageView];
        [pinView setPinColor:MKPinAnnotationColorPurple];
        [pinView setAnimatesDrop:YES];
        [pinView setCanShowCallout:YES];
        [pinView setCalloutOffset:CGPointMake(-8.0f, 0.0f)];
        // [pinView setSelected:YES animated:YES];

        UIButton *botonBrujula = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        //UIButton *botonBrujula = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];        
        //[botonBrujula setImage:[UIImage imageNamed:@"icono_mapa.png"] forState:UIControlStateNormal];
        //[botonBrujula addTarget:self action:@selector(hacerZoomAlMapa) forControlEvents:UIControlEventTouchUpInside];
        // [botonBrujula addTarget:self action:@selector(verInfo) forControlEvents:UIControlEventTouchUpInside];
        [pinView setRightCalloutAccessoryView:botonBrujula];


        // Agregamos el logo de tienda unam a la vista del punto
        UIImage *image = [UIImage imageNamed:@"logo_tienda_unam.png"];
//        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

        UIButton *botonLogoTiendaUNAM = [UIButton buttonWithType:UIButtonTypeCustom];
        [botonLogoTiendaUNAM setFrame:CGRectMake(0, 0, 30, 30)];
        [botonLogoTiendaUNAM setBackgroundImage:image forState:UIControlStateNormal];

//        // Agregamos un gesture Recognizer al logo de tienda unam
//        UITapGestureRecognizer *tapGestureRecognizer_logo = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hacerZoomAlMapa)];
//        [tapGestureRecognizer_logo setNumberOfTapsRequired:1];
//        [tapGestureRecognizer_logo setNumberOfTouchesRequired:1];
//        [imageView addGestureRecognizer:tapGestureRecognizer_logo];

//        [pinView setLeftCalloutAccessoryView:imageView];
        [pinView setLeftCalloutAccessoryView:botonLogoTiendaUNAM];


 //Problema con la vista , entra en recursividad y se desborda el programa , corregir la annotation

        // Seleccionamos el pin para mostrar la informacion de 
    // [mapView selectAnnotation:annotation animated:YES];

        // Establecemos un tag a los callout views para diferenciarlos
        [[pinView rightCalloutAccessoryView] setTag:1];     // Ver Info
        [[pinView leftCalloutAccessoryView] setTag:2];      // Hacer Zoom

    } else {

        pinView.annotation = annotation;

    }


    pinView.annotation=annotation;
    return pinView;
}





- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{

[mapView selectAnnotation:self.puntoTiendaUNAM animated:YES];


}





- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    if ([control tag] == 1) {
        [self performSegueWithIdentifier:@"ver_info" sender:self];

    } else if ([control tag] == 2) {
        [self hacerZoomAlMapa];
    }
}


- (void)hacerZoomAlMapa
{
    [_mapa deselectAnnotation:_puntoTiendaUNAM animated:NO];

    // Zoom al mapa para mostrar solo la region donde esta el pin, con un span de 1000 mts de radio
    MKCoordinateRegion mapRegion;
    mapRegion.center = _puntoTiendaUNAM.coordinate;
    mapRegion.span = MKCoordinateSpanMake(0.01, 0.01);
    [_mapa setRegion:mapRegion animated:YES];

    [_mapa selectAnnotation:_puntoTiendaUNAM animated:NO];
}

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    // Volvemos a mostrar el callout, por default es 'animated = YES'
    [_mapa performSelector:@selector(selectAnnotation:animated:) withObject:_puntoTiendaUNAM afterDelay:0.5f];
}


- (IBAction)seleccionarTipoMapa:(id)sender
{
    UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
    NSInteger indiceSeleccionado = [segmentedControl selectedSegmentIndex];

    switch (indiceSeleccionado) {

        case 0:     // Mapa tipo Normal
            [_mapa setMapType:MKMapTypeStandard];
            break;

        case 1:     // Mapa tipo Hibrido
            [_mapa setMapType:MKMapTypeHybrid];
            break;

        case 2:     // Mapa tipo Satelite
            [_mapa setMapType:MKMapTypeSatellite];
            break;

        default:
            break;
    }
}

@end

Edit with Anna suggestions The code is

  • Are you sure to have an image ? , try to `UIImage *img = [UIImage imageNamed:@"bolita_mapa.png"]; UIImageView *pinImageView = [[UIImageView alloc] initWithImage:img]; [pinImageView setUserInteractionEnabled:YES];` put a breakpoint, and check if you really have the image... – Armand DOHM Mar 26 '14 at 21:40
  • What is the question? and you should write comments in the code in english so we all can understand. – Raul Guiu Mar 26 '14 at 21:45
  • Hi armand i tried the way you suggested but now the error of the bad access is in the line UIImage *img = [UIImage imageNamed:@"bolita_mapa.png"]; The fact is that i have the image so what can it be? –  Mar 26 '14 at 21:54
  • see : http://stackoverflow.com/questions/10998544/uiimage-imagenamed-returns-nil – Armand DOHM Mar 26 '14 at 21:57
  • Ok i have an image with resolution of bolita_mapa 30x30 and i have an bolita_mapa@2x with 35x35 what is the problem? the resolution= which is the correct resolution??? –  Mar 26 '14 at 22:22
  • resolution itself is not important in your case... check if the name is correct (upper/lower case . extension), and check if you images are copied at build time (select your target, go to tab build phases, check in copy bundle ressources). ps I don't receive info about you publish comments, please add at-sign+myname – Armand DOHM Mar 26 '14 at 22:41

1 Answers1

0

This line is causing the EXC_BAD_ACCESS:

[mapView selectAnnotation:annotation animated:YES];

You should not try to select an annotation from the viewForAnnotation delegate method itself.

Remove the call to selectAnnotation:animated: from the viewForAnnotation method.


When selectAnnotation:animated: is called, the map view needs to redraw the annotation view and show its callout. Redrawing the view causes viewForAnnotation to be called. Since in that method, the code is calling selectAnnotation:animated: it causes viewForAnnotation to get called again, and so on resulting in the crash after it runs out of memory for the recursion.

If you want to have an annotation's callout show as soon as it's added to the map, do it in the didAddAnnotationViews delegate method instead. See MKAnnotation not getting selected in iOS5 for an example of this. Also note that only one annotation can be selected (show its callout) at a time.



Unrelated to the issue but instead of setting a tag on the accessory views like this:
[[pinView rightCalloutAccessoryView] setTag:1];     // Ver Info
[[pinView leftCalloutAccessoryView] setTag:2];      // Hacer Zoom

in calloutAccessoryControlTapped, you can just directly check if control itself equals the right or left accessory view. See How to connect map annotation view buttons with database to go to another view? for an example.

Community
  • 1
  • 1
  • Thank you for your reply you are absolutely right there is a leak in memory because of recursion , i´m an absolute beginner in ios, i readed the MKAnnotation not getting selected in iOS5 but is still not realize how to implement your recommendation in the above code. –  Mar 30 '14 at 04:56
  • Technically, it is not a "leak" in memory (the app is running out of memory). Regarding selecting an annotation: How many annotations are you adding? Remember only one of them can be selected at a time. Do you know which one you want to select? What did you try in the didAddAnnotationViews delegate method? **Please edit your question and _add_ the code you tried in that delegate method (or ask a new question). Do not delete the original code from the question.** –  Mar 30 '14 at 12:38
  • Based on the code you posted, you're only adding one annotation and holding a reference to it in a property so in didAddAnnotationViews, you just need this: `[mapView selectAnnotation:self.puntoTiendaUNAM animated:YES];` –  Mar 31 '14 at 13:35
  • By the way (**completely unrelated to your question**): In viewDidLoad, NSShadowAttributeName is not being used correctly (that code will crash). See http://stackoverflow.com/questions/17129108/is-it-possible-to-draw-text-with-shadows-using-the-nsstring-uikit-additions for an example. –  Mar 31 '14 at 13:38
  • Anna you mean that i should delete the [mapView selectAnnotation:annotation animated:YES] in the ViewForAnnotation and place only a [mapView selectAnnotation:self.puntoTiendaUNAM animated:YES]; in the didAnnotationViews? –  Mar 31 '14 at 21:45
  • Ok i uploaded the new code with corrections but the fact is that the program returns to the main . –  Mar 31 '14 at 23:04
  • That crash may be related to the NSShadowAttributeName issue (see my earlier comment about it). That crash has nothing to do with the selectAnnotation fix. In viewDidLoad, comment out the `setTitleTextAttributes` line for now. –  Mar 31 '14 at 23:28
  • Anna thank you so much god bless you !!! i commented that of NSShadowAttributeName and it works !!!! if i can do anything in my life for you just tell me :) hope i can contact you!!! i`m an absolute beginner can you recommend or give me an iOS course ??? thak you so much girl!!!! –  Mar 31 '14 at 23:45