[英]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
#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.