MKPolygon ontouch detailview

He creado un MKMapView con MKPolygon basado en coorderadas. Hay múltiples polígonos en el map (mira aquí un ejemplo de lo que estoy recreando como una aplicación).

Lo que trato de hacer es cuando el usuario toca el polígono, abre una vista emergente con información sobre la location. Esta información se almacena actualmente dentro de un file Plist con las coorderadas.

Lo que tengo actualmente es que puedo get un evento táctil e imprimir en el logging que el polígono fue tocado.

La pregunta que tengo es:
¿ MKPolygonView puede usar MKPolygonView como un MKAnnotationView donde una vez que el usuario toca el pin aparece más información acerca de esa location actual?

Quiero hacer lo mismo para la vista de polígono. Cuando se toca, el usuario verá más información sobre la location que se almacena en el plist. Si es posible, ¿cuál sería la mejor forma de hacerlo funcionar?

Mi código actual está debajo.

 #import "outagempViewController.h" #import "MyAnnotation.h" #import "WildcardGestureRecognizer.h" #define METERS_PER_MILE 46309.344 @interface outagempViewController () @end @implementation outagempViewController - (void)viewDidLoad { outages = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"outages"ofType:@"plist"]]; for (NSDictionary *colonetworkingAreas in outages) { coordinateData = colonetworkingAreas[@"coords"]; test = colonetworkingAreas[@"outages"]; NSLog(@"test %@", test); coordsLen = [coordinateData count]; NSLog(@"coords %d", coordsLen); CLLocationCoordinate2D coords[coordsLen]; for (i=0; i < coordsLen; i++) { NSString *lat = coordinateData[i]; NSArray *latt = [lat componentsSeparatedByString:@","]; double latitude = [[latt objectAtIndex:0] doubleValue]; double longitude = [[latt objectAtIndex:1] doubleValue]; coords[i] = CLLocationCoordinate2DMake(latitude, longitude); } MKPolygon* poly2 = [MKPolygon polygonWithCoordinates:coords count:coordsLen]; poly2.title=@"test"; [self.mapView addOverlay:poly2]; } } - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay { { if ([overlay isKindOfClass:[MKPolygon class]]) { MKPolygonView* aView = [[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay]; int numbers = [test intValue]; if(numbers >= 10){ aView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.6]; aView.strokeColor = [[UIColor greenColor] colorWithAlphaComponent:1.0]; aView.lineWidth = 3; }else if(numbers < 10){ aView.fillColor = [[UIColor yellowColor] colorWithAlphaComponent:0.6]; aView.strokeColor = [[UIColor yellowColor] colorWithAlphaComponent:1.0]; aView.lineWidth = 3; } return aView; } return nil; } } -(void)viewWillAppear:(BOOL)animated{ CLLocationCoordinate2D zoomLocation; zoomLocation.latitude = 35.20418; zoomLocation.longitude = -89.86862; MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE); [_mapView setRegion:viewRegion animated:YES]; WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init]; tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self.mapView]; CLLocationCoordinate2D coord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; MKMapPoint mapPoint = MKMapPointForCoordinate(coord); for (id overlay in self.mapView.overlays) { if ([overlay isKindOfClass:[MKPolygon class]]) { MKPolygon *poly = (MKPolygon*) overlay; id view = [self.mapView viewForOverlay:poly]; if ([view isKindOfClass:[MKPolygonView class]]) { MKPolygonView *polyView = (MKPolygonView*) view; CGPoint polygonViewPoint = [polyView pointForMapPoint:mapPoint]; BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polyView.path, NULL, polygonViewPoint, NO); if (mapCoordinateIsInPolygon) { // debug(@"hit!"); NSLog(@"hit"); } else { NSLog(@"miss"); } } } } }; [self.mapView addGestureRecognizer:tapInterceptor]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end 

Desafortunadamente, para las superposiciones, no hay una detección táctil incorporada ni una vista de llamada como para las annotations.

Deberá realizar la detección táctil manualmente como ya lo está haciendo (y parece que debería funcionar).
(Aún más lamentable es que agregar un reconocimiento de gestos directamente a la vista de superposition no funciona; debe agregarlo al map completo y luego verificar si el punto de contacto está en cualquier superposition).

Para una vista de llamada superpuesta, una vez que haya detectado un toque en una superposition, puede crear una UIView personalizada y UIView addSubview . Sugiero agregarlo al map en lugar de la vista de superposition y es posible que pueda usar el CGPoint point que ya está calculando para determinar el marco de la vista de llamada personalizada.

Es posible que también desee mantener una reference ivar / propiedad a la vista de llamada superpuesta para que pueda eliminarse y volverse a agregar fácilmente si el usuario toca otra superposition mientras la llamada para otra superposition ya se muestra.

Otra opción que probablemente sea más fácil es crear un UIViewController personalizado y presentarlo o presionarlo. Los detalles de mostrarlo dependen de si está utilizando un controller de navigation y / o un guión gráfico.

Si su aplicación también está construida para iPad, también podría mostrar la "llamada" con un UIPopoverController .
Consulte Cómo mostrar un UIPopoverView como una anotación en la vista del map. (iPad) para un ejemplo de código (es con una anotación pero debería poder adaptarla para la superposition).


Una vez que haya identificado qué superposition fue seleccionada, debe mostrar los datos asociados que se encuentran en su origen de datos original (la matriz de outages ). En este momento, las superposiciones se crean y se agregan, pero no tienen ninguna reference al object de datos original (dictionary de outages en la matriz de outages ).

(La subclass MKPolygon para agregar una propiedad personalizada tiene problemas y soluciones y la creación de una class de MKOverlay completamente personalizada presenta muchos otros trabajos adicionales).

Para su estructura de origen de datos actual, una opción simple, rápida (y algo bruta) es establecer la propiedad de title la superposition en el índice en la matriz de interrupciones del object de interrupción asociado con la superposition. Como la propiedad del title es NSString y el índice de la matriz es un integer, lo convertiremos en una cadena:

 NSUInteger outageIndex = [outages indexOfObject:colonetworkingAreas]; poly2.title = [NSString stringWithFormat:@"%d", outageIndex]; [self.mapView addOverlay:poly2]; 

En viewForOverlay , parece que está utilizando la test (que proviene de un object de interrupción) para determinar el color del polígono. El valor de la variable de test declarada / establecida externamente no necesariamente estará sincronizado con la overlay del método de delegado que se está solicitando actualmente (el map podría llamar a viewForOverlay varias veces para la misma superposition y no necesariamente en el order en que las agregue). Tiene que recuperar el object de interrupción basado en alguna propiedad del parámetro de overlay . Dado que estamos estableciendo la propiedad de title la superposition en el índice de la interrupción:

 //int numbers = [test intValue]; <-- remove this line int outageIndex = [overlay.title intValue]; NSDictionary *outageDict = [outages objectAtIndex:outageIndex]; id outageNumbersObject = outageDict[@"outages"]; //replace id above with actual type //can't tell from code in question whether it's NSString or NSNumber int numbers = [outageNumbersObject intValue]; //use "numbers" to set polygon color... 

Finalmente, cuando se viewForOverlay una superposition, usa el mismo método que en viewForOverlay para get el object de interrupción:

 if (mapCoordinateIsInPolygon) { int outageIndex = [overlay.title intValue]; NSDictionary *outageDict = [outages objectAtIndex:outageIndex]; NSLog(@"hit, outageDict = %@", outageDict); //show view with info from outageDict... }