iOS Block的内存管理

__block与__weak对于block在ARC下内存管理

_block 变量 内部实现,实际上用一个新的__Block对象当前变量包装,block内部通过引用当前包装对象实现对于外界变量的持有。此时block内部对于__Block包装的对象为强持有,ARC如果对于当前Block有强引用,则会将当前block从栈copy到堆上,此时如果之前变量在栈上,则会一并copy到堆上。
如果block没有访问auto变量,那么block则为__NSGlobalBlock_类型。如果block访问了auto变量,MRC下或者ARC下没有强引用此block,则为__NSStackBlock
,否则就会被copy到堆上,为__NSMallocBlock_类型.
测试代码

typedef void(^Block)(void);
int age = 10;

typedef void(^Block)(void);
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block int num = 10;
        NSObject *obj = [[NSObject alloc] init];
        Block block = ^{
            num= 20;
            NSLog(@"----%d, obj=%@", num, obj);
        };
        NSLog(@"%@", ^{
            NSLog(@"age= %d", age);
        });
        NSLog(@"%@", ^{
            NSLog(@"num- %d", num);
        });
        block();
        NSLog(@"%@", block);
        NSLog(@"result___num:%d", num);
        
    }
}
/*
//控制台输出
2020-04-14 22:12:01.518998+0800 block_demo[59707:1481097] <__NSGlobalBlock__: 0x100001070>
2020-04-14 22:12:01.519416+0800 block_demo[59707:1481097] <__NSStackBlock__: 0x7ffeefbff458>
2020-04-14 22:12:01.519501+0800 block_demo[59707:1481097] ----20, obj=
2020-04-14 22:12:01.519566+0800 block_demo[59707:1481097] <__NSMallocBlock__: 0x100537e90>
2020-04-14 22:12:01.519607+0800 block_demo[59707:1481097] result___num:20
*/

用Clang编译成cpp文件,查看cpp代码结构如下

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-9.0.0 main.m

当block在栈上时,并不会对__block变量产生强引用
当block被copy到堆时, 会调用block内部copy函数(copy函数内部会调用_Block_object_assign函数)实现对__block变量形成强引用
如果是OC对象,_Block_object_assign则会根据OC对象的修饰符决定是否为强引用,如果为__weak则为弱引用,默认OC对象为强引用。
iOS Block的内存管理_第1张图片 iOS Block的内存管理_第2张图片
当__block修饰对象类型时分析
默认MRC或ARC下block内部对于__block修饰对变量包装的对象肯定是强引用,但是Block包装对象对于变量引用,ARC需要看变量是否为__weak修饰决定是否强引用,而MRC下肯定不会强引用。MRC下如果没有__block,block内部会直接指向对象,此时则是强引用!!!

你可能感兴趣的:(iOS,block)