iOS | 用于解决循环引用的block timer

作者: 无夜之星辰 | 来源:发表于2018-12-05 22:46 被阅读47次

iOS 10的时候NSTimer新增了一个带block的API:

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

苹果的官方文档里说,将这个timer本身作为参数传给block以此来避免循环引用:

/// - parameter: block The execution body of the timer; the timer itself is passed as the parameter to this block when executed to aid in avoiding cyclical references

有了这个API再也不需要繁琐的手动注销timer,结合weakSelf就可以轻松处理循环引用,如:

__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
    __strong typeof(self) strongSelf = weakSelf;
    [strongSelf printNum];
}];

在这个API出现之前,self和timer的引用关系是:
self->timer->self

现在的引用关系是:
self->timer->weakSelf

但是只有iOS 10及之后的系统才能使用此API,而我们一般都是适配到iOS 8,所以有必要扩展一下。

如何扩展?

简单点,写个category,直接复制苹果的API进去(思考API设计的时间都省了😎),然后加上前缀:

+ (NSTimer *)cq_scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block {
    return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(cq_callBlock:) userInfo:[block copy] repeats:repeats];
}

+ (void)cq_callBlock:(NSTimer *)timer {
    void (^block)(NSTimer *timer) = timer.userInfo;
    !block ?: block(timer);
}

你不是把timer作为参数传给block吗?那我也这样搞。

然后就可以像使用系统API那样使用了:

__weak typeof(self) weakSelf = self;
self.timer = [NSTimer cq_scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer *timer) {
    __strong typeof(self) strongSelf = weakSelf;
    [strongSelf printNum];
}];

最后提供一个此timer使用的具体demo:
https://github.com/CaiWanFeng/CQCountDownButton

相关文章

网友评论

  • 阿唯不知道:这里为什么要这样使用strongSelf呢?

    __weak typeof(self) weakSelf = self;
    self.timer = [NSTimer cq_scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer *timer) {
    __strong typeof(self) strongSelf = weakSelf;
    [strongSelf printNum];
    }];
    CepheusSun:编程习惯而已,这个不用强行抬杠吧。写 RAC 你不写 @strongify(self) 试试?
    阿唯不知道:@无夜之星辰 为什么还要用__strong去引用weakSelf呢?printNum方法并不是timer的啊,既然都已经走了block了为什么还怕它提前释放了呢
    无夜之星辰:你觉得这里有什么问题吗

本文标题:iOS | 用于解决循环引用的block timer

本文链接:https://www.haomeiwen.com/subject/ahxwcqtx.html