在mapView regionDidChangeAnimated中获取exec错误的访问错误

时间:2014-06-18 04:11:13

标签: ios objective-c ios7

我正在使用showAnnotations方法在iOS7中的MKMapView上显示我的标记。有时它可以完美地显示所有注释但有时它会给出EXEC_BAD_ACCESS错误。

这是我的代码。

NSArray *annotations = MapView.annotations;
_mapNeedsPadding = YES;
[MapView showAnnotations:annotations animated:YES];

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
    if(_mapNeedsPadding){
        [mapView setVisibleMapRect:mapView.visibleMapRect edgePadding:UIEdgeInsetsMake(100, 20, 10, 10) animated:YES];
        _mapNeedsPadding = NO;
    }
}

1 个答案:

答案 0 :(得分:1)

在显示的代码中,您获得了EXC_BAD_ACCESS,因为调用setVisibleMapRect会导致regionDidChangeAnimated再次被地图视图调用,从而开始无限递归。

即使你使用布尔标志_mapNeedsPadding来阻止这种递归,问题是该标志在 NO之后被设置为setVisibleMapRect 已被调用(并且已经调用regionDidChangeAnimated,并且该标志永远不会设置为NO)。

因此,您的代码调用setVisibleMapRect会导致regionDidChangeAnimated再次被调用,从而导致无限递归,从而导致堆栈溢出,导致EXC_BAD_ACCESS


"快速修复"是在
调用_mapNeedsPadding之前设置setVisibleMapRect

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
    if(_mapNeedsPadding){
        _mapNeedsPadding = NO; // <-- call BEFORE setVisibleMapRect
        [mapView setVisibleMapRect:mapView.visibleMapRect edgePadding:UIEdgeInsetsMake(100, 20, 10, 10) animated:YES];
    }
}


但是,我不建议采用这种方法。

相反,您应该根据要显示的注释手动计算MKMapRect,并从主代码(而不是setVisibleMapRect:edgePadding:animated:)调用showAnnotations:animated:

并且,不要在regionDidChangeAnimated 中实施或执行任何操作。

示例:

NSArray *annotations = MapView.annotations;
//_mapNeedsPadding = YES;
//[MapView showAnnotations:annotations animated:YES];

MKMapRect rectForAnns = MKMapRectNull;
for (id<MKAnnotation> ann in annotations)
{
    MKMapPoint annPoint = MKMapPointForCoordinate(ann.coordinate);

    MKMapRect annRect = MKMapRectMake(annPoint.x, annPoint.y, 1, 1);

    if (MKMapRectIsNull(rectForAnns))
        rectForAnns = annRect;
    else
        rectForAnns = MKMapRectUnion(rectForAnns, annRect);
}

UIEdgeInsets rectInsets = UIEdgeInsetsMake(100, 20, 10, 10);

[MapView setVisibleMapRect:rectForAnns edgePadding:rectInsets animated:YES];


//Do NOT implement regionDidChangeAnimated...
//- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
//    if(_mapNeedsPadding){
//        [mapView setVisibleMapRect:mapView.visibleMapRect edgePadding:UIEdgeInsetsMake(100, 20, 10, 10) animated:YES];
//        _mapNeedsPadding = NO;
//    }
//}