zoukankan      html  css  js  c++  java
  • block之---循环引用

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

  • 相关阅读:
    mysql数据库的相关练习题及答案
    数据库一
    python的协程
    jquery的常用知识点
    diehard–让你的程序更健壮
    迷宫塔生成工具
    编程解决谁是凶手的问题
    ClojureScript实现xpath定位器生成-1
    使用ClojureScript进行chrome扩展开发
    AES CBC模式下的Padding Oracle解密
  • 原文地址:https://www.cnblogs.com/mengfei90/p/5145821.html
Copyright © 2011-2022 走看看