block 类型&如何避免循环引用&__weak/__block

类型

1. 全局
/// 1. 未引用外部变量就是一个 全局变量
void (^block)(void) = ^{

};
NSLog(@"%@,指针地址:%p",block,&block);

/// 控制台输出:
/// <__NSGlobalBlock__: 0x1027ae0a8>,指针地址:0x7ffeed4525d8
/// 2. 未引用外部变量就是一个 全局变量
NSLog(@"%@",^{

});
NSLog(@"%@",^{});

///控制台输出:
///<__NSGlobalBlock__: 0x10bf8c0e8>
  • x
  • x
2. 栈
/// 1. 引用外部变量   
/// 2. 未对 block copy 操作
int a = 10;
NSLog(@"%@",^{
     NSLog(@"%d",a);
});
// 控制器输出
//<__NSStackBlock__: 0x7ffee214a5b8>
  • x
  • x
3. 堆
/// 1. 引用外部变量   
/// 2. 对 block copy 操作
int a = 10;
void (^block)(void) = ^{
    NSLog(@"%d",a);
};
NSLog(@"%@,指针地址: %p",block,&block);
/// 控制台输出
/// <__NSMallocBlock__: 0x6000032532a0>,指针地址: 0x7ffee32d75d0
  • x
  • x

总结

  1. 一共有三种类型的Block.分为__NSGlobalBlock,__NSStackBlock,__NSMallocBlock.
  2. 没有访问 auto变量 的block 就是 __NSGlobalBlock
    访问了auto变量 的block 就是 __NSStackBlock
    当一个__NSStackBlock调用了copy操作,返回的就是一个__NSMallocBlocksing
  3. 在ARC环境下,编译器会自动把栈上的block copy到堆上
block_memory.jpeg

解决循环引用的方法

  1. block外部使用 __weak 修饰: 内部使用时 防止被释放 使用__strong 修饰:
    weakSelf -> block -> weakSelf
__weak typeof(self) weakSelf = self;
self.block = ^{

     // 1. 因为__weak 是弱引用,block块中对self 没有强引用,而异步等操作会有延时情况,因此会有延时操作发生时,self 就已经被释放的尴尬局面
     // 2. 这个 强引用只在这个作用区间有用,当这个区间结束后 ,__strong 所持有的会被完全释放。不影响外部的引用计数
     // 3. 这个区间也就是下面的区间
     //  4. __strong 就是为了防止,在进行 异步操作前,weakSelf 就已经被释放的尴尬问题,
     //  5. 若没有延时操作 也可不必使用 __strong 修饰
     __strong typeof(self) strongSelf = weakSelf; 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
             
     });
};
  1. block前 __strong 修饰,
    blockSelf -> block -> blockSelf
// 1. __block 修饰的变量可以在,block中直接修改变量
// 2. __block 是强引用 所以要在block 使用完进行置nil,解除对self 的引用 ,,,,置nil 后,下次调用,就会出问题
// 3. 最好不要用 __block 修饰self ,也没必要,因为没有什么场景直接修改self的,
// 
__block typeof(self) blockSelf = self;
self.block = ^ {

     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          blockSelf = nil;
     });  
}
  1. 传参
self.block = ^ (ViewController *vc) {
      

}

__weak 和 __block 的区别

  1. __block

优点:

  • 扩大变量的作用域(可以在block内修改外部变量)。
  • 控制对象的生命周期,防止循环引用。???? // 并不能防止循环引用
  • 是强引用,在非ARC环境下可以使用 __block替代__weak
  1. __weak

优点:

  • 弱引用,防止循环引用

你可能感兴趣的:(block 类型&如何避免循环引用&__weak/__block)