我有以下代码,它给了我一个EXC_BAD_ACCESS。
我有一张地图,我正在加载一个圆形图像,代表地图中的实际位置。
此处编辑是完整代码
#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
使用Anna建议进行编辑 代码是
答案 0 :(得分:0)
此行导致EXC_BAD_ACCESS:
[mapView selectAnnotation:annotation animated:YES];
您不应尝试从viewForAnnotation
委托方法本身中选择注释。
从selectAnnotation:animated:
方法移除对viewForAnnotation
的号召。
调用selectAnnotation:animated:
时,地图视图需要重绘注释视图并显示其标注。重新绘制视图会导致调用viewForAnnotation
。因为在该方法中,代码正在调用selectAnnotation:animated:
,导致viewForAnnotation
再次被调用,依此类推导致在递归内存耗尽后崩溃。
如果您想在注释的标注添加到地图后立即显示,请改为使用didAddAnnotationViews
委托方法。有关此示例,请参阅MKAnnotation not getting selected in iOS5。另请注意,一次只能选择一个注释(显示其标注)。
[[pinView rightCalloutAccessoryView] setTag:1]; // Ver Info
[[pinView leftCalloutAccessoryView] setTag:2]; // Hacer Zoom
在calloutAccessoryControlTapped
中,您可以直接检查control
本身是否等于右侧或左侧附件视图。有关示例,请参阅How to connect map annotation view buttons with database to go to another view?。