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

posted @ 2019-09-24 10:56  小菜看代码  阅读(473)  评论(0编辑  收藏  举报