Block简单理解
2016-04-04 本文已影响225人
云之君兮鹏
Block块的一点总结
希望大家指正 共同进步
- block是一个匿名函数
- Block定义分为三个部分:返回值类型,参数列表,block实体部分{}
返回值类型(^block名字)(参数)=^
{
如果有返回值,那么使用return;
}```
- OC语言中有三种block
``` /**
*_NSConcreteGlobalBlock:全局静态block 不会访问任何外部变量
*_NSConcreteStackBlock:保存在栈区的block,当函数返回时会被销毁
*_NSConcreteMallocBlock:保存在堆区block 引用计数为0时,会被销毁;
*/```
- 第一问:在block内部是否可以访问外部变量 答:可以
- 第二问:在block内部你能否改变外部变量的值 答:不可以
- 第三问:内外变量地址是否一样 答:不一样
```` int i=0;````
``` NSLog(@"外部%p",&i);```
```void(^block1)()=^void()
{
NSLog(@"内部访问外部变量%d",i);
i=20;错误
NSLog(@"内部%p",&i);
}```;
``block1()``;
- 第四问:如果我们想改变外部变量怎么办
答: 使用static全局修饰
- 第五问:不允许使用全局修饰
答:使用__block 杠杠两个杠修饰变量
>block与blok外部定义的变量之间的关系,在block中可以访问局部变量 不能修改
block与__block之间修饰的局部变量之间的关系,可以修改可以访问
block与static修饰的静态变量关系可以访问可以修改
> 举例分析:
__block int i=0;
int j=0;
int *q=&j;
int* p =&i;
NSLog(@"\n1---外部i=%d,j=%d,i的地址%p,i指针p的地址%p,q的地址%p",i,j,&i,&p,&q);
void(^b1)()=^void()
{
*p=*p+1;
*q=*q+1;
NSLog(@"\n2---内部i=%d,j=%d,i的地址%p,i指针p的地址%p,q的地址%p",i,j,&i,&p,&q);
};
b1();
i=i+1;
j=j+1;
NSLog(@"\n13---外部i=%d,j=%d,i的地址%p,i指针p的地址%p,q的地址%p",i,j,&i,&p,&q);
/**
结果如下
``` 1---外部i=0,j=0,i的地址0x7fff5e252df8,
i指针p的地址0x7fff5e252dc8,
q的地址0x7fff5e252dd0
2---内部i=0,j=0,i的地址0x7ffb1bc184f8,
i指针p的地址0x7ffb1bc3a078,
q的地址0x7ffb1bc3a080
3---外部i=1,j=2,i的地址0x7ffb1bc184f8,
i指针p的地址0x7fff5e252dc8,
q的地址0x7fff5e252dd0
依次分析:
__block修饰的i 在block内部复制他的内容重新开辟了空间,并且让他也变成和内部一样的地址, 也就是也可以访问也可以修改*p是i原来的地址上的值改变了也不会影响新的地址上的值 最后执行block内部的时候i=0(从原来的地方拷贝的)出来后加1变成1;
j 未被修饰 内部打印是拷贝过来的换了(开辟)空间存的值0,*q=*q+1这一步里面q变量在内部换了自己地址但是存的内容是j的值地址所以改变了外部变量j(0)的值(0+1) 出了blockj的值变成1再加1最后是外部打印变为2
j, p, q,这三个变量均没有被__block修饰所以在内部会开辟空间把值复制过去从而进行访问,出来后还是原来的地址 */````
- __weak和__block
```` //1__block在ARC 和 MRC下都能使用_weak只能在ARC下
//2__weak只能修饰对象__block都可以修饰
//3__block在block里面可以重新复制.__weak不可以
//4_block引起引用计数_weak不会````
- block写成copy1是为了安全 2是从栈区拷贝到堆区block在栈区存在时间随生命周期,在堆区我们随时调用````