注册

iOS 如何正确的使用NSTimer



1、属性传值循环引用

如:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TabelViewCell *cell = ...
cell.tableView = tableView;
return cell;
}

@interface TableViewCell: UITableViewCell
@property (nonatomic, strong) UITableView *tableView;
@end

cell 添加到tableView上被tanleView强引用,cell中tableView被强引用,造成循环引用;

所以cell中tableView应该用weak关键字

2、delegate属性用strong关键字循环引用

定义:
@interface Class A: NSObject
@property (nonatomic, strong) BView *someView;
@property (nonatomic, strong) XXXDelegate delegate;

调用:
self.someView.delegate = self;

class A强引用BView, BView的代理指向A,因为delegate是strong关键字修饰,所以BView会强引用A的实例,造成循环引用

所以delegate关键字应该用weak修饰


3、block接获变量,循环引用

self.block = ^{
self.someProperty = xxx;
}

self持有block,block截获self(这一点我也没搞太明白),赋值会把block copy到堆上,持有相关变量,就是self持有block,block又持有self,形成循环引用

解决方式:

__weak typeOf(self) weakSelf = self;
self.block = ^{
weakSelf.someProperty = xxx;
}

延展:

但这种方式可能会造成内存提前回收,比如说:block中不是简单的赋值操作,而是一个耗时的网络请求,block中的操作还没有结束,self被释放掉了,这个时候seakSelf为nil,所以someProperty无法赋值

解决方式:

__weak typeOf(self) weakSelf = self;
self.block = ^{
__strong typeOf(self) strongSelf = weakSelf;
strongSelf.someProperty = xxx;
}

原理: block中强引用self,所以self在要被释放时检查到引用计数不为0,所以系统无法释放self实例,只有等待block执行完毕,block内存被释放的时候,才会释放掉self,所以someProperty赋值成功

4、NSTimer循环引用

例如:

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

调用:
self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];

这个类似于delegate,把timer的target指向了self,所以可以用weak的方式解除循环引用;

但是在实际的代码使用过程中,timer一般需要加入到runloop中,被runloop强引用,所以timer强引用viewController, runloop强引用timer,ViewController pop后无法释放,具体可以查看这篇博客对NSTimer的分析https://www.jianshu.com/p/d4589134358a

所以可以采用另一种方式解决循环引用:

__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf timerRun];
}];

注意:timer释放前需要invalidate


链接:https://www.zhihu.com/question/34123925/answer/1181846112

0 个评论

要回复文章请先登录注册