文档章节

第04天实战技术(06):Block循环引用

宇鸿165
 宇鸿165
发布于 2017/03/29 10:55
字数 788
阅读 9
收藏 0

#####一、Block循环引用

/**
    循环引用 : 我引用你,你引用我,就会造成循环引用,双方都不会被销毁,导致内存泄漏
 */

  1. presentViewController和dismissViewController的内存管理
1.当{}过后,mdVC这个对象会被销毁,但是self.presentedViewController 管理着mdVC

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    ModalViewController *mdVC = [[ModalViewController alloc]init];
    [self presentViewController:mdVC animated:YES completion:nil];
    NSLog(@"%@",self.presentedViewController);
}

2.当dismissViewController,mdVC就会别销毁了
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 如果控制器被dissmiss 就会被销毁
    [self dismissViewControllerAnimated:YES completion:nil];
}

2.block的循环引用 A界面:ViewController B界面:ModalViewController

  • 2.1.当一个界面调用了自身的block,并且里面没有使用  弱指针的变量__weak typeof(self) weakSelf = self;会出现循环引用。
#import "ModalViewController.h"

@interface ModalViewController ()

@property(nonatomic) void(^block)();

@end

@implementation ModalViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
    
// 弱指针 (包装 __weak typeof (self) weakSelf = self;)
    // typeof(self) 相当于 ModalViewController *
    // __weak typeof(self) weakSelf = self;
    // block造成循环引用: Block 默认 会对里面所有强指针变量 都 强引用一次 (self)
    _block = ^{
        NSLog(@" -- %@",self); // 要使用弱指针 __weak typeof(self) weakSelf = self;
    };
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 如果控制器被dissmiss 就会被销毁
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)dealloc
{
    NSLog(@"%s 销毁了",__func__);
}

@end
  • 2.2.在一个延迟执行block的注意点。我们可能在外面已经设置弱指针的对象防止循环引用,但是可能会在延迟用户可能通过快速、或者是网络出现问题: 我们获取的对象可能已经是空的了
1.如果不添加         __strong typeof(weakSelf) strongSelf = weakSelf;那么可能获取的weakSelf 是空的

#pragma 0.防止循环引用 在block内部使用 要使用弱指针对象
    __weak typeof(self) weakSelf = self;
    _block = ^{
        // NSLog(@" -- %@",weakSelf);

#pragma 局部变量
#pragma 1.block延迟操作 要在block里面 要使用强引用指针
        __strong typeof(weakSelf) strongSelf = weakSelf; // 这里使用强引用 是因为害怕用户快速点击,防止在两秒延迟拿到的 weakSelf 是空的
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@" -- %@",strongSelf);

        });
    };
    
    _block();

6_1block的weak延迟执行可能获取对象是空的.png

6_2block延迟执行弱强引用配合使用解决循环引用和对象为空的问题.png


code ViewController

/**
    循环引用 : 我引用你,你引用我,就会造成循环引用,双方都会不会被销毁,导致内存泄漏
 */

#import "ViewController.h"
#import "ModalViewController.h"


@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    ModalViewController *mdVC = [[ModalViewController alloc]init];
    // self.presentedViewController 管理着mdVC
    [self presentViewController:mdVC animated:YES completion:nil];
     NSLog(@"%@",self.presentedViewController);

}

@end

ModalViewController

#import "ModalViewController.h"

@interface ModalViewController ()

@property(nonatomic) void(^block)();

@end

@implementation ModalViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
    
    // block造成循环引用: Block 默认 会对里面所有强指针变量 都 强引用一次 (self)
    
    // 弱指针 (包装 __weak typeof (self) weakSelf = self;)
    // typeof(self) 相当于 ModalViewController *
#pragma 0.防止循环引用 在block内部使用 要使用弱指针对象
    __weak typeof(self) weakSelf = self;
    _block = ^{
        // NSLog(@" -- %@",weakSelf);

#pragma 局部变量
#pragma 1.block延迟操作 要在block里面 要使用强引用指针
        __strong typeof(weakSelf) strongSelf = weakSelf; // 这里使用强引用 是因为害怕用户快速点击,防止在两秒延迟拿到的 weakSelf 是空的
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@" -- %@",strongSelf);
//            NSLog(@" -- %@",weakSelf);

        });
    };
    
    _block();
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 如果控制器被dissmiss 就会被销毁
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)dealloc
{
    NSLog(@"%s 销毁了",__func__);
}

@end

© 著作权归作者所有

宇鸿165
粉丝 1
博文 919
码字总数 368963
作品 0
广州
私信 提问
JavaScript 30天每日效果图

JavaScript 30天每日效果图 在Github上看到了wesbos的一个Javascript30天挑战的repo,旨在使用纯JS来进行练习,不允许使用任何其他的库和框架,该挑战共30天,我会在这里复现这30天遇到的挑战...

黎跃春
2017/07/19
0
0
iOS中Block循环引用刨根问底

序言 Blocks是苹果出的轻量型回调方式,使用起来既简洁,又方便。不过就是会产生一个问题:循环引用。进而会导致内存释放不了,造成内存泄漏。那到底怎么样才会产生循环引用呢?如何解决呢? ...

FlyOceanFish
2018/10/30
0
0
__block在什么情况下使用

以下为转发 API Reference对block变量修饰符有如下几处解释: //A powerful feature of blocks is that they can modify variables in the same lexical scope. You signal that a block ca......

jackyzouf
2015/09/08
74
0
(iOS)如果你使用过block,最好看一下这篇文章

首先,本文并不会涉及太多block的源码,更多的是block使用方面的一些东西。 新人写文,如有错误,敬请斧正! 原理 使用也好认识也好,首要任务就是搞懂block到底是个什么东西,其中的内容我们...

Perfect_dream
2017/11/24
0
0
唐巧的《iOS开发进阶》 - 读后感

唐巧的《iOS开发进阶》 - 读后感 为什么要看书 为什么要多看书呢? 在技术类书籍上,看书的目的,不是为了记住所有的技术,而是为了积累相关的技术,在需要用到时能够信手拈来。 此书的定位 ...

电电樺
2018/01/15
18
0

没有更多内容

加载失败,请刷新页面

加载更多

rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0
简述TCP的流量控制与拥塞控制

1. TCP流量控制 流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。...

鏡花水月
今天
10
0
OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
1K
11
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部