1、Block
1>block的标准定义
a.block是一个变量,是一个事先准备好的代码块,在需要的时候调用,也就是说block变量是一个用于保存行为的变量,有助于建模
b.标准定义
返回值 (^block变量名)(形参数列表) = 返回值^(形参列表){//block主体实现};
=左边和inlineBlock的左边一样
2>block在使用外部变量的时候,会在堆区copy一个外部变量的只读(默认)副本,在block中使用的是堆区副本,与外部变量互不影响,后续再对该变量进行修改是不会影响block当中的值的。eg:
int i = 10;//这里的i在栈区定义
void (^myBlock)() = ^{
NSLog(@“%d”,i); //这里的i是外部的栈区i在堆区的副本
}
i = 100;//这里的i在栈区定义
myBlock();
此时的block当中的i还是10而不是100;也可以理解为block的调用就是回调到block定义的位置,此时的i值还没有改变
3>如果想要block当中的局部变量的数值变化,就需要添加__block(表示NSMutable)关键字修饰局部变量,而且使用了__block修饰的局部变量在block中不再只有只读属性,是可以在block内部修改__block修饰的局部变量的
4>block类型的属性定义需要strong(ARC)或者retain(非ARC),这里可以使用copy(木有arc之前的做法)即兼容ARC和非ARC
注意:(inlineBlock定义代码块)
0>block调用前判断block是否有值
1>默认的block外部变量,在block中是只读的,用__block修饰的外部变量,才可以修改,负责编译 报错的。
2>在无__block修饰的情况下,代码块是可以修改成员变量属性的(使用较少)
3>为保证block中代码的正常运行,外部对象再传入block内部的时候会自动被block强引用,直到block结束
4>block作为oc的数据类型也可以像对象一样被存入数组,作为数组元素就会被强引用
5>block是c语言的东西,“()”在定义时不能少
6>block内部使用self一定要注意考虑,小心循环引用eg:
因为在使用外部变量的时候会在堆区给外部变量copy一个副本,从而强引用这个外部变量,(要在block当中用到某个属性,那么就必须先在堆区copy一个属性所在的对象,着样才能拿到属性)
/** block的常见面试题3 */
void demo4()
{
NSMutableString* strM = [NSMutableStringstringWithString:@"zhangsan"];
NSLog(@"=>堆区 %p栈区 %p", strM, &strM);
void (^myBlock)() = ^{
//修改字符串内容,并没有修改字符串的指针地址
[strMsetString:@"lisi"];
NSLog(@"%@", strM);
NSLog(@"堆区 %p栈区 %p", strM, &strM);
};
myBlock();
}