基本概念
block是代码段,是一段允许执行的代码,有些编程语言将其称之为闭包(closure),是iOS4之后新增的语法,
block兑现格式一个C级别的语法和运行机制,它与标准的C函数类似,不同之处在于它除了有可执行的代码以外,还包含了与堆,栈内存绑定的变量,因此,block包含着一组状态数据,这些数据在程序执行时用于对行为产生影响,你可以用block来写一些可以传到API中的函数语句,可选择性的存储,并可以使用多线程作为一个回调,block特别的有用,因为block既包含了回调期间的代码,又包含了了执行期间需要的数据。由于OC,C++,都衍生于C,那么block被设计为兼容这三种语言。
在OC中block可以定义为属性,方法参数,临时变量等
block的基本形式
//
无参无返回值
void (^demo1)() = ^(){
};
// 有参无返回值
void (^demo2)( int , int ) = ^( int a, int b){
};
// 无参有返回值
int (^demo3)() = ^(){
return 0 ;
};
// 有参有返回值
int (^demo4)( int , int ) = ^( int a, int b){
return a+b;
void (^demo1)() = ^(){
};
// 有参无返回值
void (^demo2)( int , int ) = ^( int a, int b){
};
// 无参有返回值
int (^demo3)() = ^(){
return 0 ;
};
// 有参有返回值
int (^demo4)( int , int ) = ^( int a, int b){
return a+b;
};
block的typedef
//
给一个
int
类型,有两个
int
类型参数的
block
起了一个别名为
temp
,注意:这种写法是一种数据类型直接可以创建
block
,这和宏是有别的,宏是编译器特性,作用只是替换
typedef int (^temp)( int , int );
int main( int argc, const char * argv[]) {
@autoreleasepool {
temp sum = ^( int a, int b){
return a+b;
};
NSLog ( @"%d" ,sum( 1 , 2 ));
}
return 0 ;
typedef int (^temp)( int , int );
int main( int argc, const char * argv[]) {
@autoreleasepool {
temp sum = ^( int a, int b){
return a+b;
};
NSLog ( @"%d" ,sum( 1 , 2 ));
}
return 0 ;
}
block定义成参数
- (void)callDemo:(void(^)())task
{
// 接收到外界传入的block,在这个方法里面调用一下
task();
}
block定义成参数
@interface ViewController ()
@property (nonatomic,assign) int num;
/// block定义成属性
@property (nonatomic,copy) void (^PropertyBlock)();
@end
block访问和修改外部的变量
注:默认在block内是不允许修改外部变量的,如果想修改必须用__block来标示变量,让编译器知道这个变量是在block内部做修改操作的。
在ARC的环境中block访问和修改外部变量
- 单纯的定义一个block,那么block存放在全局区
- block访问外部变量的时候,外部变量在内存中存储区域的变化:
- 访问前变量存放在栈区,访问时变量存放在栈区,访问后变量存放在栈区
- block修改外部变量的时候,外部变量在内存中存储区域的变化:
- 修改前变量存放在栈区(被__block修饰后存储位置不受影响),修改时变量存放在堆区,修改后变量存放在堆区
在MRC的环境中block访问和修改外部变量
在MRC的环境中block访问和修改外部变量,外部变量的存储区域不改变,依然是存放在栈区
block在OC中定义为属性要用copy修饰
在MRC的环境中,block存放在栈区,不能全局共享,要想实现全局共享要把其copy到堆区,这是原因所在,那么在ARC环境中strong和copy效果是一样的,但是苹果官方推荐还是用copy修饰