本文介绍了对NSTimer目标的引用不足,以防止保留周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在这样使用NSTimer:

timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(tick) userInfo:nil repeats:YES];

当然,NSTimer将保留目标,这将创建一个保留周期.此外,self不是UIViewController,所以我没有像viewDidUnload这样的东西可以在其中使计时器无效以中断周期.所以我想知道是否可以使用弱引用:

Of course, NSTimer retains the target which creates a retain cycle. Furthermore, self isn't a UIViewController so I don't have anything like viewDidUnload where I can invalidate the timer to break the cycle. So I'm wondering if I could use a weak reference instead:

__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];

我听说计时器必须无效(我想从运行循环中将其释放).但是我们可以在dealloc中做到这一点,对吧?

I've heard that the timer must be invalidated (i guess to release it from the run loop). But we could do that in our dealloc, right?

- (void) dealloc {
    [timer invalidate];
}

这是可行的选择吗?我已经看到人们处理此问题的很多方法,但是我还没有看到.

Is this a viable option? I've seen a lot of ways that people deal with this issue, but I haven't seen this.

推荐答案

建议的代码:

__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];

具有以下效果:(i)对自我的弱引用; (ii)读取弱引用以提供指向NSTimer的指针.用弱引用创建NSTimer不会产生效果.该代码与使用__strong引用之间的唯一区别是,如果将self释放在给定的两行之间,则将nil传递给计时器.

has the effect that (i) a weak reference is made to self; (ii) that weak reference is read in order to provide a pointer to NSTimer. It won't have the effect of creating an NSTimer with a weak reference. The only difference between that code and using a __strong reference is that if self is deallocated in between the two lines given then you'll pass nil to the timer.

您能做的最好的事情是创建一个代理对象.像这样:

The best thing you can do is create a proxy object. Something like:

[...]
@implementation BTWeakTimerTarget
{
    __weak target;
    SEL selector;
}

[...]

- (void)timerDidFire:(NSTimer *)timer
{
    if(target)
    {
        [target performSelector:selector withObject:timer];
    }
    else
    {
        [timer invalidate];
    }
}
@end

然后您将执行以下操作:

Then you'd do something like:

BTWeakTimerTarget *target = [[BTWeakTimerTarget alloc] initWithTarget:self selector:@selector(tick)];
timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:target selector:@selector(timerDidFire:) ...];

或者甚至将类方法添加到形式为+scheduledTimerWithTimeInterval:target:selector:...的BTWeakTimerTarget中,以创建该代码的更整洁的形式.您可能需要公开真实的NSTimer,以便可以invalidate进行编辑,否则建立的规则将是:

Or even add a class method to BTWeakTimerTarget of the form +scheduledTimerWithTimeInterval:target:selector:... to create a neater form of that code. You'll probably want to expose the real NSTimer so that you can invalidate it, otherwise the rules established will be:

  1. 计时器未保留实际目标;
  2. 真正的目标开始(可能已经完成)释放之后,计时器将触发一次,但是触发将被忽略,然后计时器失效.

这篇关于对NSTimer目标的引用不足,以防止保留周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 08:14