iOS 使用CADisplayLink、NSTimer有什么注意点?

本文探讨了在iOS开发中使用CADisplayLink和NSTimer时可能遇到的强引用问题及计时不准现象。由于强引用导致控制器无法释放,解决方案包括使用弱引用或更换实现方式。计时不准源于RunLoop的工作机制,可使用GCD计时器提高精度。同时提供了GCD计时器的封装示例。
摘要由CSDN通过智能技术生成

强引用问题

我们平时使用NSTimer或者CADisplayLink,如果不加处理直接使用系统提供的API方法,就有可能出现强引用问题(的英文注意强引用循环引用)。

场景:控制器A-> push->控制器B,控制器B的实现如下:

#import "ViewControllerB.h"

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

@implementation ViewControllerB

- (void)viewDidLoad {
    [super viewDidLoad];
    //每隔一秒钟调用一次timerTest
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES];
}

- (void)timerTest
{
    NSLog(@"%s", __func__);
}

- (void)dealloc
{
    NSLog(@"%s", __func__);
    [self.timer invalidate];
}
@end

由控制器A进入控制器B,定时器开始工作,但当点击返回,由B页面返回A页面时,会发现控制器Bdealloc方法没有调用,说明控制器B并没有销毁。

那么这是为什么呢???是因为循环引用问题??,嗯,看着像,因为控制器B强引用timertimer创造时引用target(即控制器B)产生强引用,从而产生了强引用。 ,实际上也不能算错,因为目前来看确实是有循环引用。但是当你把控制器Btimer的引用替换弱引用即:

@property (weak, nonatomic) NSTimer *timer;

你会惊讶的发现,前面的问题依旧存在。那么这又是为什么呢????,理应来说,控制器B弱引用timer,那么当- (void)viewDidLoad 方法执行完,timer的作用域就结束了,应该挂掉才对,实际上却没有,说明应该有别的对象强引用着timer别的对象事实如此,这个其实就是Runloop对象。有源码为证(参考自GNUStep):

+ (NSTimer*) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
                     target: (id)object
                   selector: (SEL)selector
                   userInfo: (id)info
                    repeats: (BOOL)f
{
  id t = [[self alloc] initWithFireDate: nil
                   interval: ti
                 target: object  // timer会强引用object
                   selector: selector
                   userInfo: info
                repeats: f];
  [[NSRunLoop currentRunLoop] addTimer: t forMode: NSDefaultRunLoopMode];
  RELEASE(t);
  return t;
}

可以看到,timer创建³³之后的英文直接加入到了当前的Runlo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值