В целом, это выглядит хорошо, но в методе filterAnnotations
есть проблема с тем, как аннотации удаляются из массива annotationsToFilter
.
Что произойдет, так это то, что некоторые аннотации будут пропущены и никогда не пройдут проверку.
Например:
- Скажем, есть 5 аннотаций (0 = A, 1 = B, 2 = C, 3 = D, 4 = E)
- Цикл for начинается с индекса 0, и «A» удовлетворяет условию удаления
- «A» удаляется из массива, и теперь другие аннотации перемещаются вниз на один индекс, поэтому после удаления массив выглядит так: (0 = B, 1 = C, 2 = D, 3 = E)
- Теперь цикл for переходит к следующему индексу, который равен 1 (поэтому проверяется аннотация C)
- Таким образом, аннотация B пропускается и никогда не проверяется
Один из способов исправить это - собрать аннотации, которые вы хотите сохранить в другом массиве «annotationsToAdd», вместо того, чтобы удалять их из оригинала, и передавать annotationsToAdd методу addAnnotations
.
Ниже предложена модификация. Я также рекомендовал бы перемещать вызовы viewForOverlay
вне цикла for, так как эти ссылки не будут меняться во время цикла, поэтому нет необходимости вызывать их повторно.
-(void)filterAnnotations:(NSMutableArray *)annotationsToFilter
{
NSMutableArray *annotationsToAdd = [NSMutableArray array];
//Get a reference to the overlay views OUTSIDE the for-loop since
//they will remain constant so there's no need to keep calling
//viewForOverlay repeatedly...
MKPolygonView *polygonView = (MKPolygonView *)[mapView viewForOverlay:polygonOverlay];
MKCircleView *circleView = (MKCircleView *)[mapView viewForOverlay:circleOverlay];
for (int i=0; i < [annotationsToFilter count]; i++)
{
//get a handy reference to the annotation at the current index...
id<MKAnnotation> currentAnnotation = [annotationsToFilter objectAtIndex:i];
CLLocationCoordinate2D mapCoordinate = [currentAnnotation coordinate];
MKMapPoint mapPoint = MKMapPointForCoordinate(mapCoordinate);
CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];
CGPoint circleViewPoint = [circleView pointForMapPoint:mapPoint];
BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);
BOOL mapCoordinateIsInCircle = CGPathContainsPoint(circleView.path, NULL, circleViewPoint, NO);
if ( !mapCoordinateIsInPolygon && !mapCoordinateIsInCircle )
//Note the reversed if-condition because now
//we are finding annotations we want to KEEP
{
[annotationsToAdd addObject:currentAnnotation];
}
}
[mapView addAnnotations:annotationsToAdd];
}
Также я заметил, что в методе showKmlData
вы используете переменную mapview
, но в filterAnnotations
это mapView
(прописные буквы V
). Надеюсь, компилятор выдаст вам предупреждение об этом.
Дополнительная информация:
Основываясь на ваших комментариях и коде
viewForOverlay
, который вы добавили к своему вопросу ...
Во-первых, предупреждение компилятора class 'MKPolygonView' does not implement the 'MKOverlay' protocol
, которое вы получаете, подразумевает, что переменные polygonOverlay
и circleOverlay
объявлены как MKPolygonView
и MKCircleView
вместо MKPolygon
и MKCircle
.
Во-вторых, код в методе делегата viewForOverlay
неверен. Он пытается создать представление круга и многоугольника для всех передаваемых overlay
, а , а затем проверяет, какой класс является оверлеем. Также кажется, что сохраняется ссылка на оверлей view , но остальная часть кода предполагает, что мы сохраняем ссылку на оверлей (объект MKOverlay
- не MKOverlayView
).
Попробуйте следующие изменения ...
//polygonOverlay and circleOverlay should be declared as MKOverlay objects...
@property (nonatomic, retain) MKPolygon *polygonOverlay;
@property (nonatomic, retain) MKCircle *circleOverlay;
//save a reference to them when you call addOverlay...
self.polygonOverlay = [MKPolygon polygonWithCoordinates:polyCoords count:coordsCount];
[mapView addOverlay:polygonOverlay];
self.circleOverlay = [MKCircle circleWithCenterCoordinate:cirleCenter radius:circleRadius];
[mapView addOverlay:circleOverlay];
//the viewForOverlay delegate method...
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
{
if ([overlay isKindOfClass:[MKCircle class]])
{
MKCircleView* circleView = [[[MKCircleView alloc] initWithOverlay:overlay] autorelease];
circleView.fillColor = [UIColor blueColor];
circleView.strokeColor = [UIColor blueColor];
circleView.lineWidth = 5.0;
circleView.alpha = 0.20;
return circleView;
}
else
if ([overlay isKindOfClass:[MKPolygon class]])
{
MKPolygonView *polygonView = [[[MKPolygonView alloc] initWithOverlay:overlay] autorelease];
polygonView.fillColor = [UIColor blueColor];
polygonView.strokeColor = [UIColor blueColor];
polygonView.lineWidth = 5.0;
polygonView.alpha = 0.20;
return polygonView;
}
return nil;
}
Вы также упоминаете в своей правке, что "Я вижу наложения, круги и многоугольники". Звучит так, будто вы создаете более одного круга и / или наложения полигонов. В этом случае наличие только одной переменной polygonOverlay и circleOverlay не будет работать.
Если у вас действительно есть несколько оверлеев каждого типа, не храните ссылки на оверлеи. Вместо этого, в методе filterAnnotations
, для каждой аннотации , переберите массив mapView.overlays
и выполните тест viewForOverlay
и точка-полигон во вложенном цикле.