本人从事这么久,发现周边还是很多从事iOS的程序猿不怎么了解block 用法,即便他们其中还有几年的开发经验,但是一跟他们聊起block,他们眼睛睁得老大。另外,很多新手程序接触block时,可能也被它搞得一头雾水,所以我决定写下这篇,供大家参考, 有问题可以评论,大家一起进步。
苹果官方对block的介绍
我从官方那里拿个图来解释下block
这张图看到了block的基本结构,如果英语不懂,没事,但是我还是希望各位可以有道一下。
一、block的基本语法
1.block的声明
int (^aBlock)(int, int);
a. 第一个int 代表aBblock的返回值类型
b. 第二个、第三个int 代表aBlock参数类型,也表明里面有2个int 类型的参数
c. (^aBlock)代表aBlock是变量名,而^则表示这个变量是block变量
d.同样,你也可以给参数起名字:
int (^aBlock)(int a,int b);
e.很多时候,我们需要将我们声明的block类型作为函数的参数,也有两种方式:
1、-(void)func:(int (^)(int a,int b))block;
f.第二种方式是通过typedef定义一种新的类型,这也是大多数情况下采用的方式:
2、typedef int (^myBlock)(int a,int b) ;
-(void)func:(myBlock)block ;
2.block的创建
aBlock = ^(int num1, int num2){
return num1 * num2;
};
a.num1代表参数1,num2代表参数2;
b.因为声明中有表示aBlock的返回值类型为int,所以需要返回一个int类型的数return num1 * num2
;
c.如果void (^aBlock)(int, int);
则代表无返回值,则不用return num1 * num2
;
上面还有简略写法(声明和创建一起来)
int (^aBlock)(int, int) = ^(int num1, int num2) {
return num1 * num2;
};
int sum = aBlock(10, 2);
NSLog(@"%d", sum);
3.访问权限
__block int a = 10; //要加__block 或者 static
int (^bBlock)(int) = ^(int num) {
a++; /* (此处不能修改的原因是在编译期间确定的,编译器编译的时候把a的值复制到block作为一个新变量(假设是a‘ = 10),此时a'和a是没有关系的。这个地方就是函数中的值传递。如果要修改就要加关键字:__block或者static)*/
return num * a;
};
int bsum = bBlock(2);
NSLog(@"bsum= %d", bsum);
//__block static 是拷贝a的指针,所以可以修改
4.回调的用法
block的回调太好用了,我们可以把耗时操作放在回调的主语部分,比如说网络请求数据的,我们可以把请求放在回调函数的”主语”部分,而获取数据部分放在回调函数的”实现”部分
下面我将要说一个回调的简单demo(部分代码摘自网上)
详细回调介绍请查看我之前写的文章
在 demo之前说下typedef 的用法
typedef void (^PresentAlertBlock)();
//typedef定义一种类型的别名,而不只是简单的宏替换,把PresentAlertBlock 这个block函数定义成一种类型
a. “主语”部分
// .h文件
typedef void (^PresentAlertBlock)();
//if改动1:typedef void (^PresentAlertBlock)(NSString* name);
@property (nonatomic, copy) PresentAlertBlock PresentAlertBlock;
-(void)startTimerCount;
//.m文件
- (void)startTimerCount {
[NSTimer scheduledTimerWithTimeInterval:6.0f target:self selector:@selector(timeCount) userInfo:nil repeats:NO];
NSLog(@"回调1");
}
//改动1:如果在定义属性,定义属性参数,那么可以通过这个传值,下面可以改动为
- (void)timeCount {
if (self.updateAlertBlock) {
self.updateAlertBlock();
NSLog(@"回调2");
}
}
/**
- (void)timeCount {
if (self.updateAlertBlock) {
self.updateAlertBlock(@"回调啦啦啦");
NSLog(@"回调2");
}
}
*/
“实现”部分
//.m文件
- (void)viewDidLoad {
[super viewDidLoad];
//[self blockMethod];
[self blockMethod2];
}
- (void)blockMethod2 {
TimerController *timer = [TimerController new];
//同样,改动1: timer.updateAlertBlock = ^(NSString *name) {}
timer.updateAlertBlock = ^(){
UIAlertController *alertcontro = [UIAlertController alertControllerWithTitle:@"点我" message:@"准备倒计时" preferredStyle:UIAlertControllerStyleAlert];
NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil);
NSString *otherButtonTitle = NSLocalizedString(@"OK", nil);
UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"cancel。。");
}];
UIAlertAction *otherButttonAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:nil];
UIAlertAction *other2 = [UIAlertAction actionWithTitle:@"praise" style:UIAlertActionStyleDefault handler:nil];
[alertcontro addAction:cancleAction];
[alertcontro addAction:otherButttonAction];
[alertcontro addAction:other2];
[self presentViewController:alertcontro animated:YES completion:nil];
};
[timer startTimerCount];
}
本页demo代码 下载