- 循环引用:(大家都知道我们OC内存管理采用引用计数机制,可自行了解)A->B , B->A ,导致无法释放就造成了循环引用
我们怎么检查循环引用呢,比较简单的是当我们pop
或则dismiss
时看我们dealloc
方法有没有执行即可,也可以自行用Xcode自带工具去分析,自行研究
几种常见循环引用
一: NSTimer,另附不常见控制器循环引用
先说个特殊例子,我们ViewController
用Strong
时
@property (nonatomic, strong) TimerCycleRef *timerVC;
_timerVC = [[TimerCycleRef alloc] initWithNibName:NSStringFromClass([TimerCycleRef class]) bundle:nil];
[self presentViewController:_timerVC animated:YES completion:^{
}];
此时会发现我们TimerCyceVC的dealloc不会执行,好了下面说NSTimer
首先我们present一个TimerCycleRef
截屏2020-08-23 下午9.48.43.png
然后创建Timer,并重写了dealloc
方法,当我们dismiss时不会执行dealloc,这是就循环引用了,demo中解释
- 创建timer
- 介绍Timer的常见方法
-
如何解决循环引用
截屏2020-08-23 下午10.31.04.png
解决方案在注释中,写了两种比较简单的方案,还有其他,可自行查资料学习
截屏2020-08-23 下午10.31.12.png
看打印log
截屏2020-08-23 下午10.30.23.png
二:block循环引用
介绍正常使用逆向传值时,是不会造成循环引用的
bVC定义一个blcok
typedef void(^MyBlcok)(NSString *str);
@interface bVC : UIViewController
@property (nonatomic, copy) MyBlcok blcok;
点击返回时,执行blcok
// 不会循环引用
// self.blcok(@"bVC --- >Hello");
// self.blcok(self.str);
self.blcok(self.label.text);
[self dismissViewControllerAnimated:YES completion:nil];
/*------------------正常用时不会循环引用的---------------------*/
// blcok界面传值用法
// 本身就没有对bvc强引用
bVC *bvc = [[bVC alloc] initWithNibName:NSStringFromClass([bVC class]) bundle:nil];
// 不会循环引用
// 当bvc被pop或者dismiss时 block也销毁了,因此当本VCdismiss时不存在被循环引用
bvc.blcok = ^(NSString * _Nonnull str) {
// 逆向传值
self.label.text = str;
};
[self presentViewController:bvc animated:YES completion:nil];
会造成循环引用的情况,自己创建,引用自己
解释都在demo中了
typedef void(^Block)(void);
@interface BlockVC ()
@property (copy, nonatomic) Block myBlock;
/*+=============造成循环引用情况==============**/
self.myBlock();
__weak typeof(self) weakSelf = self;
_myBlock = ^{
// self持有block,block持有self。
// NSLog(@"%@",self.view);
// 此时解决了循环引用,但是,需要在__strong一次,
__strong typeof(weakSelf) strongSelf = weakSelf;
// 原因: 存在有一种场景,在block执行开始时self对象还未被释放,
// 而执行过程中,self被释放了,此时访问self时,就会发生错误。
NSLog(@"%@",strongSelf.view);
};
三:UITableView
- 当我们使用cell时,cell 中的 strong 引用会造成循环引用。
@interface TestTableViewCell : UITableViewCell
@property (nonatomic, strong) UITableView *tableView; // strong 造成循环引用
@end
// datasource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TestTableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:@"UITableViewCellIId" forIndexPath:indexPath];
cell.tableView = tableView;
return cell;
}
- 解决: 假如你用xib就知道拖出来时weak。
strong 改为 weak
@property (nonatomic, weak) UITableView *tableView; // strong 改为 weak
** 四: delegate**
- 声明dellegate
@property (nonatomic, weak) id <MyDelegate> delegate;
- 如果将weak改为strong,则会循环引用