一、什么是block(块)
笔者刚学习Block的时候也是很迷惑,到底什么是block,它封装了一段代码,这段代码可以在任何时候执行。block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。(也就是把所携带的参数一起,打包返回)它和传统的函数指针很类似。
二block的定义
(1)在类中,定义一个Block变量,就像定义一个函数;
(2)Block可以定义在方法内部,也可以定义在方法外部;
(3)只有调用Block时候,才会执行其{}体内的代码;
定义:
typedef 返回值类型(^BlockName)(参数列表)
实例:typedef void(^my_block_fun)(vid){
}
// 声明和实现写在一起,就像变量的声明实现 int a = 10;
int (^MyBlock1)(int, int) = ^(int num1, int num2) {
return num1 * num2;
};
// 声明和实现分开,就像变量先声明后实现 int a;a = 10;
int (^MyBlockk2)(int,int);
MyBlock2 = ^(int num1,int num2)
{
return num1 * num2;
};
分析:
1、MyBlock1 有两个形式参数,分别为int类型;
2、MyBlock2 的返回值为int 类型;
3、等式右边就是blocks的具体实现;
4、^ 带边blocks声明和实现的标示(关键字);
可以定义其他形式的block。无返回值,无形式参数等;
//这样有等号=相当于 声明=实现 写在一起
void (^MyBlock3)() = ^()
{
int a = 10;
printf("num = %d",a);
};
分析:
1、左边为声明 一个 返回类型 为空(void)函数名为 (^MyBlock3) 参数值为()没有定义 的block
2、右边为实现MyBlock3这个函数
blocks 访问权限问题
blocks可以访问局部变量,但是不能修改。
int a = 10;
int (^dBlock)(int) = ^(int num)
{
a++;//not work!
return num * a;
};
此处不能修改的原因是在编译期间确定的,编译器编译的时候把a的值复制到block作为一个新变量(假设是a‘ = 10),此时a’和a是没有关系的。
这个地方就是函数中的值传递。如果要修改就要加关键字:__block或者static
__block int a = 7;
int (^dBlock)(int) = ^(int num)
{
a++;// work!
return num * a;
};
三、Block的基本实现-传值
第一步
创建两个视图控制器,在Aview视图控制器中创建一个UILabel和一个UIButton,其中UILabel是为了显示Bview控制器传过来的字符串,UIButton是为了push到Bview。
第二步
Bview的只有一个UITextField,是为了输入文字,当输入文字,并且返回Aview,Bview消失的时候,Bview界面上TextFiled中的文字传给Aview,并且显示在UILabel上。
1、在Bview视图控制器的.h文件中定义声明Block属性
#import <UIKit/UIKit.h>
//定义block的名字
typedef void (^ReturnTextBlock)(NSString *showText);
@interface BView : UIViewController
//定义block的属性
@property (nonatomic, copy) ReturnTextBlock returnTextBlock;
@end
2、实现Bview控制器的方法
#import "BView.h"
@interface BView ()
//写在.h文件是 外部接口 写在.m文件中 是内部调用没有暴露接口 不想被外部调用就写在.m文件中
//创建用来输入的 UITextField
@property (nonatomic,weak) UITextField* inputTF;
@end
@implementation BView
- (void)viewWillDisappear:(BOOL)animated {
//1.判断写入的值是否为空
//2.不为空则实现把输入存到returnTextBlock
if (self.returnTextBlock != nil) {
self.returnTextBlock(self.inputTF.text);
}
}
@end
实现Aview控制器的方法引用
BViewController *BView=[[BViewController alloc]init];
BView.returnTextBlock = ^(NSString *returnStr) {
NSLog(@"%@",returnStr);
};
[self.navigationController pushViewController:BView animated:YES];
四、Block的用途
**假设A有一个任务,是去仓库取一张A4纸放到会议室,然后在纸上写一份策划书。取纸又要经过仓库管理员,于是A通知仓库管理员来张纸过来。由于管理员是个老头动作很慢,另外A还有其他工作,如果一直等待管理员就太浪费时间了,合理的做法是让仓库管理员进行取纸这项工作,A在通知管理员后就继续自己的工作。A不知道仓库管理员什么时候能完成取纸,也就不知道什么时候可以在纸上写策划书。这时block机制就派上用场了,使用这种机制,可以让A在通知仓库管理员取纸的同时,告诉仓库管理员将纸放到编号XX会议室,并安排好将要在纸上写的策划内容,当管理员把纸拿来后,可能过一会就会有个助理将策划内容写到纸上。假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣**