block内部引用外界对象的原则:block会对他内部所有的强指针进行强引用。

验证原理:

在主控制器中modal出ModalVC控制器,ModalVC中有强引用的block属性,在block内部使用self,此时ModalVC便不会被释放,不会执行dealloc方法。

验证代码:

循环引用的情况:

#import "ModalVC.h"

@interface ModalVC ()
// block属性
@property (nonatomic, strong) void(^block)();
@end @implementation ModalVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor]; // 定义block属性
self.block = ^{
NSLog(@"%@", self);
}; // 调用block
self.block();
} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 返会上一层控制器
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)dealloc { NSLog(@"ModalVC is release");
}
@end

改进方法: 将创建一个弱引用的self,供block内部使用

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor]; // 创建弱引用的self
__weak typeof(self) weakSelf = self;
// 定义block属性
self.block = ^{
NSLog(@"%@", weakSelf);
}; // 调用block
self.block();
}

block在多线程中问题

block中使用的对象可能会被提前释放。
#import "ModalVC.h"

@interface ModalVC ()
// block属性
@property (nonatomic, strong) void(^block)();
@end @implementation ModalVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor]; // 创建弱引用的self
__weak typeof(self) weakSelf = self;
// 定义block属性
self.block = ^{
// 延时执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"%@", weakSelf);
});
}; // 调用block
self.block();
} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 返会上一层控制器
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)dealloc { NSLog(@"ModalVC is release");
}
@end

在此种情况下,在ModalVC被modal出来后立即点击屏幕,打印结如下,说明ModalVC在延时中的block执行时已经被提前释放了,这种情况并不是我们想要的。

2016-01-16 10:06:19.206 004-block的循环引用问题[1863:54052] ModalVC is release
2016-01-16 10:06:19.547 004-block的循环引用问题[1863:54052] (null)

内存分析

当ModalVC被VC控制器modal出来时,它被VC的presentedViewController属性强引用,当点击屏幕时,ModalVC控制器被dismiss掉了,presentedViewController强指针就无效了,ModalVC因为没有强指针指向,就会被释放掉,block也会被释放掉,但是dispatch_after中的Block并没有被释放(被系统强引用着),两秒后执行时打印出的weakSelf就为nil。

解决方法:

在block对象中再对weakSelf增加一个强指针

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor]; // 创建弱引用的self
__weak typeof(self) weakSelf = self; // 定义block属性
self.block = ^{
// 给weakSelf增加一个强指针
__strong typeof(self) strongSelf = weakSelf; // 延时两秒
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@", strongSelf);
});
}; // 调用block
self.block();
}

执行结果, 先打印ModalVC控制器,再释放ModalVC控制器

2016-01-16 10:57:16.837 004-block的循环引用问题[2113:80213] <ModalVC: 0x7fdcd1d26850>
2016-01-16 10:57:16.838 004-block的循环引用问题[2113:80213] ModalVC is release

内存分析

当点击屏幕时,ModalVC控制器被dismiss掉了,presentedViewController强指针就无效了,但是ModalVC控制器仍然会被dispatch_after中block的strongSelf所强引用,所以不会被释放掉。

最新文章

  1. MySQL_02之增删改查、PHP数据库操作
  2. autocad2008+C#2008开发中设置自动加载dll
  3. Photoshop 使用可选颜色
  4. Javascript中call和apply的区别与详解
  5. docker-hub 账户
  6. leetcode之Rectangle Area
  7. UML用户指南--UML图简介
  8. select * from table where 1=1让您茅塞顿开(转)
  9. NYOJ-745蚂蚁的难题(二)
  10. 用消息在Win32控制台程序多线程间进行通讯
  11. HDU 1074 Doing Homework (状态压缩 DP)
  12. [TYVJ] P1044 数字三角形
  13. js调试工具console详解
  14. java打印各种菱形
  15. Topshelf便捷创建Windows服务
  16. Paint the Grid Reloaded ZOJ - 3781 图论变形
  17. MySQL ALTER TABLE: ALTER vs CHANGE vs MODIFY COLUMN
  18. 电脑小白和ta的小白电脑
  19. kafka消费者基本操作
  20. 08.基于IDEA+Spring+Maven搭建测试项目--Maven的配置文件settings.xml

热门文章

  1. JAVA解析HTML,获取待定元素属性
  2. 【转】国外程序员收集整理的PHP资源大全
  3. iOS开发——NSDate(待续...)
  4. hisi出的H264码流结构
  5. JS 中 Class - 类创建
  6. UVa 10360 - Rat Attack
  7. Nodejs之模板ejs
  8. 2781: [JSOI2007]文本生成器
  9. JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)
  10. 【Android】Activity