__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修饰的变量
包装成一个对象,通过对象去修改其属性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)
网友评论