您的位置:首页 > 移动开发 > IOS开发

iOS--block底层代码探究

2016-08-29 15:47 281 查看
1.__block:

1.首先创建个block

int main(int argc, char * argv[]) {
@autoreleasepool {

__block int a = 10;

void (^block)() = ^{
a = 20;
};

NSLog(@"%d", a);

block();

NSLog(@"%d", a);

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}


2.通过clang -rewrite-objc来转换底层的c++代码

3.block的本质上是一个指向结构体的指针

4.默认情况下,任何block都在栈中,随时都可能会被回收。

void (^myBlock)() = ^{

};


对block做一次copy操作,block的内存就会放入堆中。

[myBlock copy]
Block_copy(myblock);(非ARC)
@property (nonatomic, copy) void (^block);


5.不用retain的原因是,retain只会使引用计数+1,但内存地址不会改变。

6.使用__weak和__unsafe_unretained的原因:

Objective-C的对象在内存中是以堆的方式分配空间的 ,而且block经过copy后的内存也是分配在堆中,所以程序结束后,变量不会被释放,会造成内存泄露。

Person *p = [[Person alloc] init];

__weak Person *p2 = p;
__unsafe_unretained Person *p2 = p;
p.block = ^{
p2.age = 20;
};


7.__block:对象可以在block中被重新赋值,在Block中截获了变量的瞬间值以后就不能再改变变量的值,如果想要在Block中改变变量的值,那么我们只需要在变量声明的时候加上__Block修饰符.

然而这样的情况又是允许的:

NSMutableArray *array = [[NSMutableArray alloc]init];
void (^blo)() = ^{
[array addObject:@"Obj"];
};


因为我们只是对截获的变量进行了操作,而没有进行赋值,所以对于截获变量,可以进行操作而不可以进行赋值

1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。

2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。

3.__block对象可以在block中被重新赋值,__weak不可以。

PS:__unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的__weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。

8.代理为什么要用weak?因为controller强引用控件,如果控件的delegate又强引用controller的话,会造成内存泄漏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  block