如何知道何时使'NSTimer`无效 [英] How to know when to invalidate an `NSTimer`

查看:75
本文介绍了如何知道何时使'NSTimer`无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题:

我有一个模型类,其中包含 NSTimer ,我想要定时器运行模型对象的整个生命周期。初始化很容易:我在 init 方法中只有以下代码行:

I have a model class that has an NSTimer in it that I want the Timer to run for the entire lifespan of the model object. Initiliazation is easy: I just have the following line of code in the init method:

self.maintainConnectionTimer = 
             [NSTimer scheduledTimerWithTimeInterval:1 
                                              target:self 
                                            selector:@selector(maintainConnection) 
                                            userInfo:nil 
                                             repeats:YES];

但是,我的问题是,如何从模型释放时使此计时器无效内存?现在,这通常很容易,但据我所知,当您安排 NSTimer 时,操作系统会维护一个指向Timer对象的强大指针。

However, my issue is, how do I invalidate this timer when the model is released from memory? Now, this would usually be easy, however, as far as I know, when you schedule an NSTimer the OS maintains a strong pointer to the Timer object.

我该如何处理?是否有一个方法在模型从内存中释放之前被调用?

How should I deal with this? Is there a method that gets called right before the model is released from memory?

推荐答案

[NSTimer scheduledTimerWithTimeInterval:...] 保留目标,因此如果目标是 self ,那么您的模型类实例将永远不会被释放。

The [NSTimer scheduledTimerWithTimeInterval:...] retains the target, so if the target is self, then your instance of the model class will never be deallocated.

作为一种解决方法,可以使用单独的对象(在以下示例中称为 TimerTarget )。 TimerTarget ModelClass 引用,以避免保留周期。

As a workaround, one can use a separate object (called TimerTarget in the following example). TimerTarget has a weak reference to ModelClass, to avoid a retain cycle.

这个助手类看起来像这样。它的唯一目的是将计时器事件转发到真实目标。

This "helper class" looks like this. Its only purpose is to forward the timer event to the "real target".

@interface TimerTarget : NSObject
@property(weak, nonatomic) id realTarget;
@end

@implementation TimerTarget

- (void)timerFired:(NSTimer*)theTimer
{
    [self.realTarget performSelector:@selector(timerFired:) withObject:theTimer];
}

@end

现在,在您的模型类中,您可以创建一个计时器并在 dealloc 中使其无效:

Now, in your model class, you can create a timer and invalidate it in dealloc:

@interface ModelClass ()
@property(strong, nonatomic) NSTimer *timer;
@end

@implementation ModelClass

- (id)init
{
    self = [super init];
    if (self) {
        TimerTarget *timerTarget = [[TimerTarget alloc] init];
        timerTarget.realTarget = self;
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                 target:timerTarget
                                               selector:@selector(timerFired:)
                                               userInfo:nil repeats:YES];
    }
    return self;
}

- (void)dealloc
{
    [self.timer invalidate]; // This releases the TimerTarget as well!
    NSLog(@"ModelClass dealloc");
}

- (void)timerFired:(NSTimer*)theTimer
{
    NSLog(@"Timer fired");
}

@end

所以我们有

modelInstance ===> timer ===> timerTarget ---> modelInstance
(===> : strong reference, ---> : weak reference)

请注意,定时器到模型类的实例不再有(强)引用。

Note that there is no (strong) reference from the timer to the instance of the model class anymore.

我已使用以下代码对其进行了测试,一个 ModelClass 的实例,并在5秒后释放它:

I have tested this with the following code, which creates an instance of ModelClass and releases it after 5 seconds:

__block ModelClass *modelInstance = [[ModelClass alloc] init];
int64_t delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    modelInstance = nil;
});

输出:

2013-01-23 23:54:11.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:12.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:13.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:14.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:15.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:15.484 timertest[16576:c07] ModelClass dealloc

这篇关于如何知道何时使'NSTimer`无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆