Block 定义

Block 定义

block 的循环引用问题

warning 如果block (block只要是copy的就会在堆中) 在堆中, block引用外界的对象, 会导致循环引用

typeof可以获取括号中传递的值的真实类型

typeof(10) a = 10; == int a = 10;

  • 如果是用__weak修饰, 当对象销毁之后会自动将变量的值设置为nil

    • 如何在开发中,避免block出现循环引用呢
    • 1>每次碰到self的时候,要小心,需要思考一下
    • 2>充分利用dealloc方法
    • 解决方法:
__weak typeof(self) weakSelf = self;
为了保证代码的安全性,苹果在设计block的时候
  • block引用外部变量时,默认会做copy操作,copy本身也会做一次强引用
  • 在现在的代码中,如果block中有对self的强引用,出现循环引用的情况
  • 解决方法,在oc中,对象默认都是强引用,__weak可以变成弱引用

block 的定义

/*定义属性,block属性可以用strong修饰,也可以用copy修饰 */ 
@property (nonatomic, strong) void(^onBtnClick)(void);          //无参无返回值
@property (nonatomic, strong) void(^myBlock1)(NSString *);            //带参数无返回值  
@property (nonatomic, strong) NSString *(^myBlock2)(NSString *);  //带参数与返回值  


// block被当做方法的参数:  
格式:(block类型)参数名称  
- (void)test:(void(^)())testBlock                    //无参无返回值  
- (void)test1:(void(^)(NSString *))testBlock         //带参数无返回值  
- (void)test2:(NSString *(^)(NSString *))testBlock   //带参数与返回值  


// 使用typedef定义block  :
typedef void(^myBlock)();                            //以后就可以使用myBlock定义无参无返回值block  
typedef void(^myBlock1)(NSString *);                 //使用myBlock1定义参数类型为NSString的block  
typedef NSString *(^myBlock2)(NSString *);           //使用myBlock2定义参数类型为NSString,返回值

// 也为NSString的block  
// 定义属性  
@property (nonatomic, strong) myBlock testBlock;  
// 定义变量  
myBlock testBlock = nil;  
// 当做参数  
- (void)test:(myBlock)testBlock;  

3、block访问和修改变量时的变化

  • block里面可以访问全局变量
  • block访问全局变量,不会修改全局变量的地址
  • block里可以访问外部局部变量

  • block访问外部局部变量,会修改外部局部变量的地址

block访问外部局部变量时,会将该局部变量复制一份到自己的内部(堆区),自己用的时候用自己内部的,外部如果使用,用栈区的
  • block里可以修改全局变量
  • block里不可以修改外部局部变量(是以const的形式复制过来的)
  • 如果我硬是要修改外部局部变量,那么就在外部局部变量前面加一个__block
  • 被__block修饰的外部局部变量,会复制一份到block内部,然后如以后用该变量,用的都是block内部的
4、前提是ARC : Block访问外部的变量
  • ARC环境下,单纯的定义一个block存储在全局区 <NSGlobalBlock: 0x1045c60b0>
  • ARC环境下,block访问外部的变量时block存储在堆区 <NSMallocBlock: 0x7fa8fd00c1b0>
  • 在block访问这个变量之前,变量在栈区
    == 0x7fff53c73bfc
  • 在block内部访问这个变量时,变量会被block拷贝到堆区
    0x7fe851517880
5、前提是ARC : Block修改外部的变量
  • ARC环境下,当block修改外部变量的时候,会在堆区
    <NSMallocBlock: 0x7f82ac8a6130>
  • 在block的外面,即使你使用__block修饰了,那么他的地址依然不变,在栈区
    0x7fff5e101bf8
  • 在block内部修改外部的变量时,使用__block修饰了外部的变量之后,外部的变量会在堆区 0x7f9d10e0bcc8
6、在MRC模式下:
  • block 变量本身在常量/全局区
  • 在block中访问局部变量,变量的地址发生了变化但存储空间没有发生变化还是在栈区 ,block本身的地址也变化到栈区
  • block在修改局部变量,变量的地址不变化,block本身的地址变化到栈区
  • *
block的循环引用问题
  • MRC 使用 __block 修饰
  • ARC下 使用 __weak修饰
  • 在block中使用self时 要把self 搞成弱引用

把self搞成弱引用的__weak ViewController *weakSelf = self;

2.把__weak是把指针搞成弱指针(引用计数不加1) : 就是告诉Block,你在引用(Copy)我的时候,别想给我的引用计数加1
__weak.ViewController *weakSelf = self;

1.在使用Block的时候,Block在访问外部的对象时,会把对象进行一次Cpoy操作;但是,Block的Copy操作会把引用计数加1.那么此时Block就会对外部的对象有强引用;如果这个外部的对象正好是self,那么Block就会对self有强引用.此时,”很容易造成”Block的循环引用

2.__weak是把指针搞成弱指针(引用计数不加1) :
就是告诉Block,你在引用(Copy)我的时候,别想给我的引用计数加
1

3.分析 : 不用__weak造成循环引用的情况

已知 : Block(op) 对 self 有强引用

求 : 满足循环引用的条件?

答: self -> queue/OPCache -> op -> self

4.队列里面的操作执行完了以后,就会把操作从队列移除,此时,这个循环引用就解除了

5.图片下载完成之后,我们手动的把下载操作从操作缓存池移除,此时,这个循环引用也就解除了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值