在MKMapView中添加注释时EXC_BAD_ACCESS

时间:2014-08-28 04:06:57

标签: objective-c memory-management mkmapview exc-bad-access mkannotation

我正在调用一个Web服务,该服务在委托方法中返回一个注释数组,我将addAnnotations方法添加到我的地图中MKMapView。一切顺利,直到委托方法快速连续发送两个数组(通常约150毫秒 - 500毫秒),然后我在这一行EXC_BAD_ACCESS (code=1 address 0x20)得到一个[kMap addAnnotations:tileArray]; - 这似乎是一个内存问题,但我不是我真的很清楚该怎么做或如何改变我的代码来解决它。

这是委托方法

-(void)rebelBaseManager:(RebelBaseManager *)manager didUpdateTileHour:(NSArray *)tileArray boundaryBreak:(NSString *)breakType atTileLevel:(int)callTileLevel {

if (timerStarted == NO) {

    [self startTimer];
}

//Check for tileLevel in case multiple calls were made at different tile levels
if (tileLevel == callTileLevel) {

    [kMap addAnnotations:tileArray];
    [HourInMap addObjectsFromArray:tileArray];
}
} 

我还添加了一种方法,允许我动画删除注释,如果它有所作为:

- (void)removeAnnotationsWithFade:(NSArray *)annotations animated:(BOOL)shouldAnimate {

if (!shouldAnimate)
    [self removeAnnotations:annotations];
else {

    for (HourAnnotation *annotation in annotations) {

        MKAnnotationView *annotationView = [self viewForAnnotation:annotation];

        [UIView animateWithDuration:2
                         animations:^{

                             annotationView.alpha =0;

                         }completion:^(BOOL finished) {

                             [self removeAnnotation:annotation];
                         }];
    }
}

--------- ADDITION ---------

在Rob的答案中添加自定义注释的代码以响应#3。

  - (id)initWithFrame:(CGRect)frame
    {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
    }


    - (id)initWithHourAnnotation:(HourAnnotation *)hourAnnotation reuseIdentifier:(NSString *)reuseIdentifier {

    CGRect  myFrame = self.frame;
    myFrame.size.width = hourAnnotation.frameSize;
    myFrame.size.height = hourAnnotation.frameSize;

    self = [super initWithFrame:myFrame]; 
     //When I use this here I seem to get the frame and color of the old annotation displayed
     //self = [super initWithAnnotation:velocityAnnotation reuseIdentifier:reuseIdentifier];
    if (self)
    {

        self.layer.cornerRadius = self.frame.size.width / 2;
        self.clipsToBounds = YES;
        [self setBackgroundColor:[UIColor clearColor]];

        NSArray *alphaValue = [[NSArray alloc]initWithArray:[self alphaForTileLevel]];


        self.fillColor = [UIColor colorWithHue:hourAnnotation.color saturation:.06 brightness:.23 alpha:[[alphaValue objectAtIndex:hourAnnotation.tileLevel-1]doubleValue]];
        self.strokeColor = [UIColor colorWithHue:hourAnnotation.color  saturation:.06 brightness:.23 alpha:.35];


        self.enabled = NO;
        self.canShowCallout = NO;
        self.userInteractionEnabled = NO;

    }

    return self;

    }


    - (void)drawRect:(CGRect)rect
{
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
    [self.fillColor set];
    [path fill];
    [self.strokeColor set];
    [path setLineWidth:2.0f];
    [path stroke];
}

1 个答案:

答案 0 :(得分:2)

一些想法。

  1. 您没有显示您调用此removeAnnotationsWithFade的位置。我们必须假设您正在删除相应的模型对象。使用仪器确认您没有泄漏到任何地方。

  2. 如果应用程序在使用淡入淡出删除时崩溃,但没有淡入淡出则崩溃,那么您可以考虑重构此代码。具体来说,您的动画代码实际上并没有删除旧动画,直到完成块(即两秒钟后)。因此,您将持续比所需更长的旧注释。如果注释快速而激烈,你可能会遇到内存问题。

    例如,如果您使用transitionWithView:mapView而只是直接删除注释,则可能会更快地释放与旧注释关联的内存。这是一个不太优雅的动画,但可能“足够好”并最小化你的峰值内存使用量:

    // this will immediately remove the annotations, but animate the fading of the transition
    
    [UIView transitionWithView:self.mapView duration:2.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        [self.mapView removeAnnotations:annotations];
    } completion:nil];
    
    // presumably remove the annotations from your array, too
    
  3. 你的viewForAnnotation出列旧注释视图,如果它不能使旧注释出现,或者它是否总是实例化新注释,那么它只是实例化新注释?这样的东西也可能有助于控制峰值内存使用量。