2010-12-03 20 views
5

Ey, como dice el título, me está resultando difícil agregar un MKPolygon como una superposición a un MKMapView. Aquí está el código correspondiente:
ParkingMapViewContoller.hProblemas Agregar MKPolygon como una superposición a un MKMapView

#import <UIKit/UIKit.h> 
#import <MapKit/MapKit.h> 


@interface ParkingMapViewController : UIViewController <MKMapViewDelegate> { 
    MKMapView *mapView; 
} 

@property (nonatomic, retain) IBOutlet MKMapView *mapView; 


-(void)loadAnnotations; 
-(void)showCurrentLocationButtonTapped:(id)sender; 


@end 

ParkingMapViewController.m

//... 
#import "ParkingRegionOverlay.h" 
//... 
- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSLog(@"%@",self.title); 

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:100 target:self action:@selector(showCurrentLocationButtonTapped:)]; 

    /*MKMapPoint points[3] = {{38.53607,-121.765793}, {38.537606,-121.768379}, {38.53487,-121.770578}}; 
    MKPolygon *polygon = [MKPolygon polygonWithPoints:points count:3];*/ 

    ParkingRegionOverlay *polygon = [[ParkingRegionOverlay alloc] initialize]; 
    [mapView addOverlay:polygon]; 

    [self loadAnnotations]; 

    CLLocationCoordinate2D centerCoord = { UCD_LATITUDE, UCD_LONGITUDE }; 
    [mapView setCenterCoordinate:centerCoord zoomLevel:13 animated:NO]; //from "MKMapView+ZoomLevel.h" 
} 
//... 

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay 
{ 
    NSLog(@"in viewForOverlay!"); 

    if ([overlay isKindOfClass:[MKPolygon class]]) 

    { 

     MKPolygonView* aView = [[[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay] autorelease]; 

     aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; 

     aView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7]; 

     aView.lineWidth = 3; 

     return aView; 

    } 
    return nil; 
} 
//... 

ParkingRegionOverlay.h

#import <Foundation/Foundation.h> 
#import <MapKit/MapKit.h> 


@interface ParkingRegionOverlay : NSObject <MKOverlay> { 
    //CLLocationCoordinate2D origin; 
    MKPolygon *polygon; 

    //MKMapRect rect; 
} 

//@property (nonatomic) CLLocationCoordinate2D origin; 
@property (nonatomic, retain) MKPolygon *polygon; 

//@property (nonatomic) MKMapRect rect; 

-(ParkingRegionOverlay*)initialize; 
-(MKMapRect)boundingMapRect; 
-(CLLocationCoordinate2D)coordinate; 

@end 

ParkingRegionOverlay.m

#import "ParkingRegionOverlay.h" 


@implementation ParkingRegionOverlay 

//@synthesize origin; 
@synthesize polygon; 

//@synthesize rect; 


-(ParkingRegionOverlay*) initialize { 
    MKMapPoint points[3] = {{38.53607,-121.765793}, {38.537606,-121.768379}, {38.53487,-121.770578}}; 
    polygon = [MKPolygon polygonWithPoints:points count:3]; 
    polygon.title = @"Some Polygon"; 
    return self; 
} 

- (MKMapRect)boundingMapRect{ 
    MKMapRect bounds = MKMapRectMake(-121.770578,38.537606,-121.770578-(-121.765793),38.537606-38.53487); 
    return bounds; 
} 

- (CLLocationCoordinate2D)coordinate{ 
    return CLLocationCoordinate2DMake((38.537606-38.53487)/2, (-121.770578-(-121.765793))/2); 
} 

@end 

Ves que NSLog me quedé en el viewForOverlay: método? Bueno, eso nunca aparece en la consola, por lo que nunca se llama a la función. ¿Alguna idea de lo que está mal? ¡Muchas gracias!

Respuesta

10

El principal problema es que el código está dando a la vista de mapa de latitud/longitud coordina donde espera MKMapPoints. Para obtener una explicación de la diferencia, consulte "Descripción de la geometría del mapa" en el Location Awareness Programming Guide. Use la función MKMapPointForCoordinate para convertir las coordenadas lat/long a MKMapPoint.

El segundo problema es que en viewForOverlay, está comprobando si la superposición es del tipo MKPolygon. Su clase de superposición ParkingRegionOverlay contiene un objeto MKPolygon dentro de ella, pero no es de tipo MKPolygon.

para solucionar el problema principal, es necesario cambiar la inicialización y métodos boundingMapRect:

-(id)init { 
    if (self = [super init]) { 
     MKMapPoint points[3]; 
     CLLocationCoordinate2D c1 = {38.53607,-121.765793}; 
     points[0] = MKMapPointForCoordinate(c1); 
     CLLocationCoordinate2D c2 = {38.537606,-121.768379}; 
     points[1] = MKMapPointForCoordinate(c2); 
     CLLocationCoordinate2D c3 = {38.53487,-121.770578}; 
     points[2] = MKMapPointForCoordinate(c3); 

     polygon = [MKPolygon polygonWithPoints:points count:3]; 
     polygon.title = @"Some Polygon"; 
    } 
    return self; 
} 

- (MKMapRect)boundingMapRect{ 
    CLLocationCoordinate2D corner1 = 
     CLLocationCoordinate2DMake(38.537606, -121.770578); 
    MKMapPoint mp1 = MKMapPointForCoordinate(corner1); 

    CLLocationCoordinate2D corner2 = 
     CLLocationCoordinate2DMake(38.53487, -121.765793); 
    MKMapPoint mp2 = MKMapPointForCoordinate(corner2); 

    MKMapRect bounds = 
     MKMapRectMake(mp1.x, mp1.y, (mp2.x-mp1.x), (mp2.y-mp1.y)); 

    return bounds; 
} 

Por favor, observe por la forma en que he cambiado el método de "inicialización" a "init". Aunque no impidió que se mostrara el polígono, la forma en que se anula la inicialización de ParkingRegionOverlay utilizando un método llamado "initialize" y no llama a [super init] no sigue la convención. (También elimine "initialize" del archivo .h.)

Para el montaje de la segunda cuestión, el método viewForOverlay debería tener este aspecto:

- (MKOverlayView *)mapView:(MKMapView *)mapView 
    viewForOverlay:(id <MKOverlay>)overlay 
{ 
    NSLog(@"in viewForOverlay!"); 

    if ([overlay isKindOfClass:[ParkingRegionOverlay class]]) 
           //^^^^^^^^^^^^^^^^^^^^ 
    { 
     //get the MKPolygon inside the ParkingRegionOverlay... 
     MKPolygon *proPolygon = ((ParkingRegionOverlay*)overlay).polygon; 

     MKPolygonView *aView = [[[MKPolygonView alloc] 
      initWithPolygon:proPolygon] autorelease]; 
          //^^^^^^^^^^ 

     aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; 
     aView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7]; 
     aView.lineWidth = 3; 

     return aView; 
    } 
    return nil; 
} 

Finalmente, cambie el código en viewDidLoad:

ParkingRegionOverlay *polygon = [[ParkingRegionOverlay alloc] init]; 
[mapView addOverlay:polygon]; 
[polygon release]; //don't forget this 
+0

Olvidé explicar por qué viewDidOverlay no se ha llamado aunque se haya establecido el delegado de vista de mapa (que debe serlo independientemente). El método viewDidOverlay solo se invoca cuando el boundingMapRect de la superposición esté visible en la región actual. , no se consideró "visible" y viewDidOverlay no se llamaba. – Anna

+0

Dang man, realmente sabes tus cosas. Increíble ... ¡Gracias, hombre! no tengo idea de cuánto tiempo he estado tratando de hacer que eso funcione. Ah, y mientras estoy en el tema, ¿cómo voy a hacer una llamada emergente de la superposición cuando se toca? No hace falta una explicación larga, pero si pudieras indicarme un método o un documento, sería genial. ¡Muchas gracias! – Stunner

+1

Lamentablemente, una vista de superposición no tiene un rótulo incorporado como MKAnnotationView, por lo que se necesita más trabajo. Puede usar un UIGestureRecognizer para detectar el toque (consulte [esta respuesta] (http://stackoverflow.com/questions/4317810/how-to-capture-tap-gesture-on-mkmapview)). Use un solo toque, doble toque, mantenga presionada, lo que sea que funcione para usted. Sin embargo, el doble toque entrará en conflicto con el zoom. En esa respuesta, en el método handleGesture, puede verificar si el punto de contacto está en el boundingMapRect de la superposición usando MKMapRectContainsPoint y luego abrir una vista emergente. – Anna

0

me parece que se olvida de establecer su delegado algo como que

_mapView.delegate = auto;

+0

pensamiento agradable, pero no, configurarlo a través de IB y el mapView está conectado a ParkingMapViewController para que de hecho sea el delegado de mapView. También tengo anotaciones en el mapa que muestran y funcionan correctamente, lo que no sería el caso si no hubiera especificado ParkingMapViewController para ser el delegado de la vista del mapa. – Stunner

+0

sugeriría que establezca el delegado programáticamente en lugar de en IB. – justicepenny

+0

Establecerlo programáticamente, pero todavía no hay suerte. :( – Stunner

0

se ha marcado esto ?:

yourMap.delegate=self; 

Y cuál es su objetivo? 3.xo 4.x? Creo que MKPolygon está disponible desde 4.0. Puede intentar agregar la cláusula de importación para que su archivo de prefijo como:

#ifdef __OBJC__ 
#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 
#import <MapKit/MapKit.h> 
#endif 
+0

Target es 4.1. Intenté configurar mi delegado tal como lo especificó en el método viewDidLoad en vano. También probé su versión de la cláusula de importación, pero no tuve suerte. ¿Alguna otra idea? – Stunner

+0

intente configurar su variable MKMapView como 'IBOutlet MKMapView mapView;' – Mat

+0

Ya lo tengo así en la declaración @property, y estoy seguro de que no va a hacer nada. Sin embargo, lo intenté y no funcionó. – Stunner

Cuestiones relacionadas