彻底分析block中的循环引用
来源:互联网 发布:mac 查杀进程 编辑:程序博客网 时间:2024/06/05 20:03
我做了一个被push到的controller,pop的时候,controller会释放,解析详见注释,欢迎批评指正!
#import "AnimaViewController.h"@interface AnimaViewController ()@property (nonatomic, strong) UIView *view1;@property (nonatomic, strong) UIView *view2;@property (nonatomic, copy) void (^block)(int);//self持有了block@property (nonatomic, strong) UIButton *btn;@property (nonatomic, strong) NSTimer *timer;@end@implementation AnimaViewController__weak AnimaViewController *weakSelf;//用弱引用来跟踪self的释放情况。- (void)viewDidLoad { weakSelf = self;//指向self的弱引用。 [super viewDidLoad]; self.view1 = [[UIView alloc]initWithFrame:CGRectMake(0, 100, 90, 90)]; self.view1.backgroundColor = [UIColor orangeColor]; [self.view addSubview:self.view1]; self.view2 = [[UIView alloc]initWithFrame:CGRectMake(0, 300, 90, 90)]; self.view2.backgroundColor = [UIColor blueColor]; [self.view addSubview:self.view2]; self.btn = [[UIButton alloc]init]; self.btn.backgroundColor = [UIColor blackColor];; [self.btn setFrame:CGRectMake(100, 100, 80, 80)]; [self.btn addTarget:self action:@selector(tapAction:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.btn]; //系统有时候会提示你可能导致循环引用,但会有漏掉的情况,比如strong变量定义成全局变量的时候。 __weak AnimaViewController *weakSelfLocal = self;//弱引用,引用计数不会增加。 self.block = ^ (int num){ __strong AnimaViewController *strongSelf = weakSelfLocal;//增加了对self的引用计数。 [strongSelf.btn setTitle:[NSString stringWithFormat:@"%d", num] forState:UIControlStateNormal]; [strongSelf.btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; //此后strongSelf变量作为局部strong变量,被系统发送了release消息(编译时就已插入release),所以strongSelf已经不构成对self的引用。如果将__weak AnimaViewController *weakSelfLocal定义为全局变量,那么此处strongSelf不会被release,所以仍然保持对self的强引用,则会导致循环引用。此处定义strong变量的用意是防止self被释放,导致此处的操作失效。 }; self.block(100); NSLog(@"%@", weakSelf);//此处self没有被释放,所以对它的弱引用变量weakSelf不为null。 //关于注册通知中的block:The block is copied by the notification center and (the copy) held until the observer registration is removed.可见block中不能持有self的强引用,否则只有解除注册的时候,才能释放对self的持有,而self只有释放的时候才会在dealloc中解除通知的注册,则导致循环引用。所以要用弱引用代替self。 [[NSNotificationCenter defaultCenter]addObserverForName:@"blockretaincycle" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { [weakSelfLocal.btn setTitle:[NSString stringWithFormat:@"%d", 888] forState:UIControlStateNormal]; [weakSelfLocal.btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; }]; //runloop对timer强引用,timer的target又强引用了self,self又强引用了timer,所以会循环引用,不会调用dealloc。 self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];}- (void)timerMethod{ NSLog(@"%@", [NSDate date]);}- (void)tapAction:(UIButton *)sender{ //很多系统自带的block里,可以直接用self,不会循环引用。不清楚的可以看苹果官方文档。 [UIView animateWithDuration:1.0 animations:^{ [self.view1 setFrame:CGRectMake(100, 400, 70, 70)]; } completion:^(BOOL finished) { [self.view1 setFrame:CGRectMake(100, 400, 70, 70)]; }];}- (void)dealloc{ NSLog(@"%@", weakSelf);//weakSelf是全局的,而此处打印为(null),说明self已经被释放。如果导致循环引用,则不会调用这个方法。 [[NSNotificationCenter defaultCenter]removeObserver:self name:@"blockretaincycle" object:nil];// [self.timer invalidate];//写在这里没用,不会调用的}- (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [self.timer invalidate];//写在这里,确保退出页面的时候,timer失效,不会对self强引用,self可以销毁了。}@end
0 0
- 彻底分析block中的循环引用
- Block中的循环引用问题
- 多线程block中的循环引用
- Block实现原理与Block中的循环引用问题
- 详解Block: block循环引用
- Block的循环引用
- block循环引用
- Block的循环引用
- block 防止循环引用
- block循环引用问题
- 循环引用的block
- block的循环引用
- block循环引用
- block循环引用问题
- block循环引用
- Block的循环引用
- Block的循环引用
- block循环引用问题
- 栈 函数的实现
- day13/StringMethodDemo.java
- 提高第18课时,实践4,扑克牌
- 交换*号到第一位的partition算法和不改变数字位置的算法 scala版本
- android studio慢慢熟悉-好用的 设置 查找框
- 彻底分析block中的循环引用
- UVA LA3890 二分和半平面交
- python中出现的expected an indented block错误代码解析
- CSU1614:First Blood
- 剑指offer 替换空格 java实现
- Leecode记录——Valid Palindrome
- day14/ArrayListTest2.java
- C++命名空间的解释
- 关于SmartForm和ScriptForm的输出格式设置说明