0

当我的应用程序开始在我的自定义注释方法中崩溃时,我了解到我的内存有问题。我确信管理地图的视图控制器 100% 应该已经从视图堆栈中弹出。

这是注释的代码,TaxiArrivingAnnotation.h

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

@interface TaxiArrivingAnnotation : NSObject<MKAnnotation>
@property (nonatomic) CLLocationCoordinate2D coordinate;
@property (nonatomic) int minutesToTaxiArrival;

-(void) startTimer;
@end

TaxiArrivingAnnotation.m

#import "TaxiArrivingAnnotation.h"

#define SECONDS_IN_A_MINUTE 60

@interface TaxiArrivingAnnotation ()
@property (nonatomic) NSTimer * timer;
@property (nonatomic) NSDate * timeOfArrival;
@property (nonatomic, weak) id token1;
@property (nonatomic, weak) id token2;
@end

@implementation TaxiArrivingAnnotation

- (id)init
{
    self = [super init];
    if (self) {
        __weak TaxiArrivingAnnotation * this = self;

        self.token1 = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification *note)
        {
            NSLog(@"DID BECOME ACTIVE");
            NSTimeInterval secondsLeft = [this.timeOfArrival timeIntervalSinceNow];
            if (secondsLeft < 0) {
                self.minutesToTaxiArrival = 0;
                return;
            }

            this.minutesToTaxiArrival = secondsLeft / SECONDS_IN_A_MINUTE;

            [this startTimer];
        }];

        self.token2 = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:nil usingBlock:^(NSNotification *note)
       {
           NSLog(@"WILL RESIGN ACTIVE");
           [this.timer invalidate];
           this.timer = nil;
       }];

    }
    return self;
}


-(void) setMinutesToTaxiArrival:(int)newMinutes {
    self->_minutesToTaxiArrival = newMinutes;
    self->_timeOfArrival = [NSDate dateWithTimeIntervalSinceNow:SECONDS_IN_A_MINUTE * newMinutes];
    if (newMinutes < 0) {
        [self.timer invalidate];
    }
}

-(void) startTimer {
    self.timer = [NSTimer timerWithTimeInterval:SECONDS_IN_A_MINUTE target:self selector:@selector(aMinutedPassed) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
}

-(void) aMinutedPassed {
    self.minutesToTaxiArrival--;
}

-(void) dealloc {
   NSLog(@"DEALLOC");
    if (self.timer != nil && [self.timer isValid])
        [self.timer invalidate];
    [[NSNotificationCenter defaultCenter] removeObserver:self.token1];
    [[NSNotificationCenter defaultCenter] removeObserver:self.token2];
}
@end

我正在添加注释viewDidAppear并将其删除viewDidDisappear。不仅删除它,而且nil-ing 引用。调用管理视图控制器时,该dealloc方法仍未dealloc调用。

真正的问题是计时器和通知触发并且应用程序崩溃,因为注释已被释放。

4

1 回答 1

1

您正在尝试invalidatedealloc. 问题是计时器保持对target(您的注释)的强引用,这将防止dealloc被调用(因为只有在没有更多强引用时才会调用它)。它类似于强引用循环(也称为保留循环)。

invalidate当您的视图控制器被解除分配(或任何逻辑事件是启动视图控制器的解除)时,您必须使用计时器。而且由于计时器将在您到达时失效,显然您可以从注释的方法中dealloc删除invalidate代码。dealloc

于 2013-10-11T12:55:36.477 回答