一、Block是什么?
1. 是代码段,苹果推荐的类型,效率高,在运行中保存代码。用来封装和保存代码,有点像函数,block可以在任何时候执行;
2. 代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。
脱字符(^)是块的语法标记。按照我们熟悉的参数语法规约所定义的返回值以及块的主体(也就是可以执行的代码)。
定义代码块语法:
块类型 块对象 = ^(参数列表){ 夸函数体 };
void(^myblock)() = ^(){ // 无返回值 无参数 =右边的()可以省略
NSLog(@"-------");
NSLog(@"-------");
};
int (^sumblock)(int, int) = ^(int a, int b) { // 有返回值 有参数
return a + b;
};
下图是如何把块变量赋值给一个变量的语法讲解:
按照调用函数的方式调用块对象变量就可以了:
int result = myBlock(4); // result是 28
3. 和函数的相似性:
1)可以保存代码;
2)有返回值
3)有形参
4)调用方式一样
4. 标识符:^
二、基本使用
1. 定义block变量
Int (^SumBlock)(int,int);//有参数,返回值类型为int
Void (^MyBlock)();//无参数,返回值类型为空
2. 利用block封装代码
// 利用block封装代码
// 1.接受两个参数
int (^MyBlock1)(int, int) = ^(int a, int b) {
return a + b;
};
// 2.无参数形式
int (^MyBlock2)() = ^() {
return 20;
};
// 3.无参数的省形式
// 2.无参数形式
int (^MyBlock3)() = ^ {
return 20;
};
3. Block
访问外部变量
1)Block内部可以访问外部变量;
2)默认情况下,Block内部不能修改外部的局部变量
3)给局部变量加上__block关键字(两个下划线哦),则这个局部变量可以在block内部进行修改。
如:
void test2() {
__block int c = 19;
// 声明一个block变量
// 可以使用无数多个变量进行调用
MySum sum = ^(int a, int b) {
// 如果外部的变量已经用__block关键字修饰,就可以在block内部修改这一个变量
c = 19;
return a + b;
};
NSLog(@"%i", sum(10, 10));
}
4. 利用
typedef
定义
block
类型
(
和指向函数的指针很像
)。关于tepedef的作用后面的的文章有介绍typedf讲解
Typedef int(^MyBlock)(int , int);
以后就可以利用这种类型来定义block变量了。----使用这个好处就是:可以使用无数多个变量进行调用(如下面定义了两个变量),传统的方式只能定义一个变量
MyBlock a, b;
a = ^(int a,int b){return a-b;};
MyBlock b2 = ^(int n1,int n2){return n1*n2;}
三、拓展案例
1. 参数是NSString* 的代码块
void (^print)(NSString *x);
print = ^(NSString *str){
NSLog(@"print:%@", str);
};
print(@"Hello World");
2. 代码在字符串数组排序
// 字符串
NSArray *str = [NSArray arrayWithObjects:@"abc 1", @"abc 22", @"abc 13", @"abc 0", @"abc 09", nil];
NSComparator sort = ^(id str1, id str2) {
return [str1 compare:str2];
};
NSArray *sortArray = [str sortedArrayUsingComparator:sort];
NSLog(@"sortArray:%@", sortArray);
结果是:
@class关键字[598:144356] sortArray:(
"abc 0",
"abc 09",
"abc 1",
"abc 13",
"abc 22"
)
3. 代码块要想递归调用,代码快变量必须要是全局变量或者是静态变量,这样程序启动的时候代码块变量就初始化了,就可以递归调用
static void (^ const blocks)(int) = ^(int i)
{
if (i > 0) {
NSLog(@"num:%d", i);
blocks(i - 1);
}
};
blocks(3);
4.在代码块中使用局部变脸和全局变量
int global = 1000;
int main(int argc, const char * argv[])
{
@autoreleasepool {
void(^block)(void) = ^(void)
{
global++;
NSLog(@"global:%d", global);
};
block();
NSLog(@"global:%d", global);
}
return 0;
}
局部变量要想再代码块中能够更改的话需要在block里面添加一个__(两个下划线)