nstimer循环引用_ios开发中经典循环引用场景?
1、屬性傳值循環(huán)引用
如:- (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強(qiáng)引用,cell中tableView被強(qiáng)引用,造成循環(huán)引用;
所以cell中tableView應(yīng)該用weak關(guān)鍵字
2、delegate屬性用strong關(guān)鍵字循環(huán)引用
定義:
@interface Class A: NSObject
@property (nonatomic, strong) BView *someView;
@property (nonatomic, strong) XXXDelegate delegate;
調(diào)用:
self.someView.delegate = self;
class A強(qiáng)引用BView, BView的代理指向A,因?yàn)閐elegate是strong關(guān)鍵字修飾,所以BView會(huì)強(qiáng)引用A的實(shí)例,造成循環(huán)引用
所以delegate關(guān)鍵字應(yīng)該用weak修飾
3、block接獲變量,循環(huán)引用
self.block = ^{
self.someProperty = xxx;
}
self持有block,block截獲self(這一點(diǎn)我也沒搞太明白),賦值會(huì)把block copy到堆上,持有相關(guān)變量,就是self持有block,block又持有self,形成循環(huán)引用
解決方式:
__weak typeOf(self) weakSelf = self;
self.block = ^{
weakSelf.someProperty = xxx;
}
延展:
但這種方式可能會(huì)造成內(nèi)存提前回收,比如說:block中不是簡(jiǎn)單的賦值操作,而是一個(gè)耗時(shí)的網(wǎng)絡(luò)請(qǐng)求,block中的操作還沒有結(jié)束,self被釋放掉了,這個(gè)時(shí)候seakSelf為nil,所以someProperty無法賦值
解決方式:
__weak typeOf(self) weakSelf = self;
self.block = ^{
__strong typeOf(self) strongSelf = weakSelf;
strongSelf.someProperty = xxx;
}
原理: block中強(qiáng)引用self,所以self在要被釋放時(shí)檢查到引用計(jì)數(shù)不為0,所以系統(tǒng)無法釋放self實(shí)例,只有等待block執(zhí)行完畢,block內(nèi)存被釋放的時(shí)候,才會(huì)釋放掉self,所以someProperty賦值成功
4、NSTimer循環(huán)引用
例如:
class ViewController
@property (nonatomic, strong) NSTimer *timer;
調(diào)用:
self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
這個(gè)類似于delegate,把timer的target指向了self,所以可以用weak的方式解除循環(huán)引用;
但是在實(shí)際的代碼使用過程中,timer一般需要加入到runloop中,被runloop強(qiáng)引用,所以timer強(qiáng)引用viewController, runloop強(qiáng)引用timer,ViewController pop后無法釋放,具體可以查看這篇博客對(duì)NSTimer的分析
所以可以采用另一種方式解決循環(huán)引用:
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf timerRun];
}];
注意:timer釋放前需要invalidate
總結(jié):iOS中常見的循環(huán)引用大致有這4種,根據(jù)實(shí)際的情況分析解決辦法
總結(jié)
以上是生活随笔為你收集整理的nstimer循环引用_ios开发中经典循环引用场景?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iQOO Z7官宣搭载七重护眼高规格LC
- 下一篇: 豪车?新买的奔驰C级连发故障 4S店拒绝