zoukankan      html  css  js  c++  java
  • Block 循环引用问题

    1.block是封装函数及其上下文的OC对象 

    2.Block类型 (最终都是继承自NSBlock类型)

    • __NSGlobalBlock __ 在数据区
    • __NSMallocBlock __ 在堆区
    • __NSStackBlock __ 在栈区
    • 堆:动态分配内存,需要程序员自己申请,程序员自己管理
    • 栈:自动分配内存,自动销毁,先入后出,栈上的内容存在自动销毁的情况

    3.block的属性修饰词为什么是copy

    block一旦没有进行copy操作,就不会在堆上

    block在堆上,程序员就可以对block做内存管理等操作,可以控制block的生命周期

    4.block属性的建议写法(基于MRC、ARC所以一般用copy)

    MRC
    @property (copy, nonatomic) void (^block)(void);

    ARC
    @property (strong, nonatomic) void (^block)(void);
    @property (copy, nonatomic) void (^block)(void);

    5.在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上的几种情况?

    • 1.block作为函数返回值时
    • 2.将block赋值给__strong指针时
    • 3.block作为Cocoa API中方法名含有usingBlock的方法参数时
    • 4.block作为GCD API的方法参数时

     

    6.__block 修饰符作用?

    __block可以用于解决block内部无法修改auto变量值的问题

    __block不能修饰全局变量、静态变量(static)

    编译器会将__block变量包装成一个对象

    7.如何解决block循环引用的问题?(现在一般使用__weak解决)

    MRC

    两种方式:__unsafe_unretained、__block

    ARC

    三种方法比较

    • __weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil(使用不当会使对象提前释放)
    • __unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变
    • __block:必须把引用对象置位nil,并且要调用该block

    8.block循环引用(AB有持有关系,且在block中调用了彼此的某些变量)

    Block一般作为参数 属性 返回值形式 使用

    产生循环引用的条件是—— AB有持有关系,且在block中调用了彼此的某些变量(AB系统的或者自定义的都可以)

    特例1 .block作为Cocoa API中方法名含有usingBlock的方法参数时(编译器会自动处理,我们不需要处理)

    //        LJYBLOCK: enumerateObjectsUsingBlock;  A(self)与B(topArray)有持有关系 但未循环引用 是个例外

    //        WeakObj(self);

            [self.topArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

                if (idx == 0) {

                    ICKTrendAttentionViewController *vc = [[ICKTrendAttentionViewController alloc] init];

                    vc.view.frame = CGRectMake(0, 0, LL_ScreenWidth, LL_SafeScreenHeight-ICKTopViewHeight);

    //                [Weakself addChildViewController:vc];

                    [self addChildViewController:vc];

                    

                } else  {

                    ICKTrendSquareViewController *vc = [[ICKTrendSquareViewController alloc] init];

                    vc.view.frame = CGRectMake(0, 0, LL_ScreenWidth, LL_SafeScreenHeight-ICKTopViewHeight);

                    [self addChildViewController:vc];

                    

                    

                }

            }];

    特例2

    UIAlertController *alerController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];

    //        LJYBLOCK:  UIAlertController  AB没有持有关系 不会循环引用

        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

            [self pop];

            //        LJYBLOCK:  UIAlertController 系统的未循环引用 自己定义的不行  基本不会出现 仅仅为了测试

    //        alerController.message = @"123";

        }];

    参考博客:

    https://www.jianshu.com/p/4e79e9a0dd82

  • 相关阅读:
    支付相关备忘
    大文件跨服务器传送
    redis与memcache区别总结
    linux grep 查找字符串
    db2 连接报错connect。 ERRORCODE=-4499, SQLSTATE=08001(转载)
    linux查看匹配内容的前后几行(转)
    weblogic线程阻塞性能调优(图解)转
    ThreadPool has stuck threads
    Shell脚本中调用另外一个脚本的方法
    MUTT+MSMTP利用163服务器发送邮件
  • 原文地址:https://www.cnblogs.com/lijianyi/p/11577092.html
Copyright © 2011-2022 走看看