繁体   English   中英

注释从未在ARC中调用过的dealloc方法,调用了底层的viewcontroller dealloc

[英]Annotation dealloc method never called in ARC, underlying viewcontroller dealloc is called

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

这是注释的代码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方法。

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

您正在尝试invalidate dealloc的重复计时器invalidate 问题在于计时器保留了对target (您的注释)的强引用,这将防止调用dealloc (因为只有在没有更多强引用时才调用dealloc )。 这类似于强大的参考周期(也称为保留周期)。

在释放视图控制器时(或引发关闭视图控制器的任何逻辑事件),必须invalidate计时器invalidate 而且由于计时器将在您到达dealloc invalidate ,因此显然可以从注释的dealloc方法中删除invalidate代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM