程序员iOS Developer互联网科技

block-__block修饰符和__block内存管理

2018-07-03  本文已影响52人  RM_乾笙

__block修饰符的特点

1.__block可以用于解决block内部无法修改auto变量值的问题
2.__block不能修饰全局变量、静态变量(static)

因在block的内部是无法修改外部的auto变量的,所以需要通过__block修饰符来修改外部auto变量的值,看看下面的一段代码:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        __block auto int age = 10;
        void (^block)(void) = ^ {
            age = 20;
            NSLog(@"age is age:%d",age);
        };
        block();
    }
    return 0;
}
// 控制台输出
2018-07-03 14:12:51.176447+0800 __block修饰符[22494:2047905] age is age:20
Program ended with exit code: 0

我们从上面main函数中可以得知,用__block修饰的auto变量,在block内部能够修改age的值,那__block在底层做了什么呢?我们来了解下,下面是clang 生成的c++源码:

block修饰符

通过上面代码分析,修饰符__block底层实际就是,编译器通过将__block修饰的变量包装成一个对象,通过对象去修改其属性age的值,所以有__block 修饰的age变量无age修饰的变量区别是很大的。

__block内存管理

#import <Foundation/Foundation.h>
#import "RMPerson.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        __block RMPerson *person = [[RMPerson alloc] init];
        void (^block)(void) = ^ {
            NSLog(@"person : %@",person);
        };
        block();
    }
    return 0;
}

-----------------RMPerson.h-----------------
#import <Foundation/Foundation.h>
@interface RMPerson : NSObject
@end

-----------------RMPerson.m-----------------
#import "RMPerson.h"
@implementation RMPerson
- (void)dealloc {
    NSLog(@"RMPerson - dealloc");
}
@end

看看上面代码通过clange转成c++的代码,如下图


block内存管理
如果__block变量被copy到堆时

1.会调用__block变量内部的copy函数
2.copy函数内部会调用_Block_object_assign函数,_Block_object_assign函数会根据所指向对象的修饰符(__strong__weak__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用(注意:这里仅限于ARC时会retain,MRC时不会retain

如果__block变量从堆上移除

1.会调用__block变量内部的dispose函数
2.dispose函数内部会调用_Block_object_dispose函数,_Block_object_dispose函数会自动释放指向的对象(release)


上一篇下一篇

猜你喜欢

热点阅读