ARC模式下的Block
前面三章都是在MRC模式下对Block进行了一系列分析,这章将讨论ARC模式下Block有什么不一样的?
int main(int argc, const char * argv[]) {
@autoreleasepool {
int a = 10;
void(^block) (void) = ^{
NSLog(@"%d", a);
};
NSLog(@"%@", block);
NSLog(@"%@", ^{NSLog(@"%d", a);});
}
return 0;
}
// 打印会发现,第一个打印的block竟然在堆区,而第二打印的block在栈区
// <__NSMallocBlock__: 0x100431750>
// <__NSStackBlock__: 0x7ffeefbff4c0>
为什么在MRC模式下,上面代码中的block在栈区,而到了ARC模式下却在堆区,那是因为在ARC模式下有些API内部会对Block进行copy,下面情况会自动对Block进行copy:
- (Block)get_block {
int index = 6;
return ^{NSLog(@"index = %d", index);};
}
- (void) autoCopyToHeap {
// 1、Block作为右值
int num = 10;
Block blk1 = ^{
NSLog(@"num = %d", num);
};
NSLog(@"<1>%@", blk1);
// 2、Block作为方法/函数返回值
NSLog(@"<2>%@", [self get_block]);
// 3、调用GCD API时,内部会copy Block
NSLog(@"执行blk3前num的内存地址:%p", &num);
__weak Block blk3 = ^{
NSLog(@"执行blk3<时>num的内存地址:%p", &num);
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), blk3);
// 4、Cocoa框架的方法且方法名含有usingBlock/block
NSLog(@"执行blk4前num的内存地址:%p", &num);
__weak void (^blk4)(NSTimer *timer) = ^(NSTimer *timer) {
NSLog(@"执行blk4<时>num的内存地址:%p", &num);
};
[[NSTimer timerWithTimeInterval:1 repeats:NO block:blk4] fire];
}