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所强引用,所以不会被释放掉。

block之---循环引用的更多相关文章

  1. 避免Block的循环引用

    避免Block的循环引用 什么是循环引用,什么时候发生循环引用 1 循环引用就是当self 拥有一个block的时候,在block 又调用self的方法.形成你中有我,我中有你,谁都无法将谁释放的困局 ...

  2. 关于block的循环引用的问题

    在block的循环引用的问题上我们都知道如果在block内部修改外部的变量的时候,要加__block以防止循环引用的问题,但是如果block是当前对象的一个属性的时候,要修改当前对象的一个属性的时候就 ...

  3. iOS开发Block的介绍以及Block的循环引用问题

    1:block的循环引用问题最主要记住两点: 如果[block内部]使用[外部声明的强引用]访问[对象A], 那么[block内部]会自动产生一个[强引用]指向[对象A] 如果[block内部]使用[ ...

  4. block的循环引用

    什么是循环引用呢? 就是我引用你,你引用我,就会造成循环引用,双方都不会被销毁,导致内存泄漏. _block =  ^{ NSLog(@"%@", self); }; block会 ...

  5. weakSelf 运用 strongSelf来解决block的循环引用

    SDWebImage 中有一段源码: #if SD_UIKIT Class UIApplicationClass = NSClassFromString(@"UIApplication&qu ...

  6. iOS - Block的循环引用内存泄漏问题探索

    循环引用的原因 众所周知,ARC下用block会产生循环引用的问题,造成泄露的原因是啥呢? 最简单的例子,如下面代码: [self.teacher requestData:^(NSData *data ...

  7. 避免在block中循环引用(Retain Cycle in Block)

    让我们长话短说.请参阅如下代码: - (IBAction)didTapUploadButton:(id)sender { NSString *clientID = @"YOUR_CLIENT ...

  8. iOS开发小技巧--键盘处理以及解决block造成循环引用的小技巧

  9. block使用小结、在arc中使用block、如何防止循环引用

    引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...

随机推荐

  1. bzoj4008: [HNOI2015]亚瑟王【期望dp】

    一个特别神奇的dp,特别厉害. f(i, j) 表示 有 j 轮发动技能的牌在 [1, i] 另外的m - j轮在[i + 1, n]之间的概率. 怎么转移呢? 首先考虑i这张牌不选的情况,f(i - ...

  2. 数据可视化-使用EXCEL和PS制作一个复杂饼图

    一个朋友让我帮忙用饼图去展现一下一堆数据,我说行,后来他给我后,我看到是一堆貌似从什么仪器中导出的一堆使用分隔符分开的文本文档,使用excel打开后如下(为了保护隐私忽略了用字母和数字代替原来的内容: ...

  3. java--面向对象编程

    instanceof的用法 静态绑定,即早期绑定,首先找父类 动态绑定,即运行时绑定,new谁找谁 Object o1 = null; //正确的语法,null也是一种特殊的引用数据类型 object ...

  4. [Angular Tutorial]PhoneCat Tutorial App

    (注:曾经在<不敢止步>一书中看到学到一个观点,作者认为学习一门技术最好的方法就是翻译某部领域书籍.这里我决定做一次尝试,接下来花1个月左右时间,将Angular Tutorial Pho ...

  5. Voilin 之 握弓

    握弓要像拿杯子,手要圆:整个手型是左倾.

  6. 用Redis作为Mysql数据库的缓存

    看到一篇不错的博文,记录下: http://blog.csdn.net/qtyl1988/article/details/39553339 http://blog.csdn.net/qtyl1988/ ...

  7. Pomelo的Filter

    在pomelo中,filter分为before filter和after filter.在一个请求到达Handler被处理之前,可以经过多个before Filter组成的filter链进行一些前置处 ...

  8. eclipse jsp html 格式化 format

    eclipse jsp html 格式化 format http://blog.csdn.net/hexin373/article/details/7677250

  9. Spring xml中进行面向切面的配置

    Spring xml中进行面向切面的配置 XML: <?xml version="1.0" encoding="UTF-8"?> <beans ...

  10. 利用apache的mod_rewrite做URL规则重写

    使用mod_rewrite做url重写,伪静态,做过很多次,这次用几个例子记下来,便于后面查用. 使用方法: 1.在conf目录的httpd.conf文件中找到: LoadModule rewrite ...