美文网首页iOS开发-高级汇总
三种Block在ARC下的分析

三种Block在ARC下的分析

作者: dacheng | 来源:发表于2016-07-14 14:58 被阅读93次

根据Block在内存中的位置,Block可分为三种类型NSGlobalBlock,NSStackBlock,NSMallocBlock。

NSGlobalBlock

这种Block存储在程序的数据区域(跟函数存储在一起),一个没有引用外部变量的Block即为NSGlobalBlock。对于NSGlobalBlock,我们不需要使用copy,即使copy,也不会copy到堆上!

NSStackBlock

如果Block中引用了外部变量,则该Block为NSStackBlock。
对于NSStackBlock,如果不做任何操作,随栈自生自灭。一旦block被调用,则会被copy到堆上,变成NSMallocBlock。
请看如下代码:

typedef void (^dBlock)();  
  
dBlock example_getBlock() {  
    char d = 'aaa';  
    return ^{  
        printf("%c\n", d);  
    };  
}  
  
void example() {  
    example_getBlock()();  
} 

上面的代码中,example_getBlock返回了一个NSStackBlock,正常情况下返回一个栈上的对象是会出错的,但是在ARC下,返回的时候会将NSStackBlock拷贝到堆上,而且是autorelease类型的。example_getBlock返回堆上的NSMallocBlock,所以上面的代码可以正常运行。

再看如下代码:

- (NSArray*) getBlockArray
{
    int num = 123;
    return [[NSArray alloc] initWithObjects:
            ^{ NSLog(@"this is block 0:%i", num); },
            ^{ NSLog(@"this is block 1:%i", num); },
            ^{ NSLog(@"this is block 2:%i", num); },
            nil];
}

- (void)test
{
    NSArray* obj = [self getBlockArray];
    void (^blockObject)(void);
    blockObject = [obj objectAtIndex:1];
    blockObject();
}

这段代码中,getBlockArray返回一个NSStackBlock数组,而ARC并没有对数组中的block做任何处理,getBlockArray函数结束后,NSArray中的三个block都将被释放。所以在test函数中,blockObject指向一块已经被释放的栈内存,运行时程序会报错。

NSMallocBlock

默认的block是存放在栈上的(NSStackBlock),对于一个NSStackBlock copy一下即可copy到堆上,变成NSMallocBlock。

相关文章

网友评论

    本文标题:三种Block在ARC下的分析

    本文链接:https://www.haomeiwen.com/subject/lbvejttx.html