block,本人之前很少用这个,传值什么的都是用代理,所以对这个不太重视,后来见了一位大牛写的代码中几乎都是block函数,看起来简洁,使用起来又方便,所以,今天稍微整理了一下,没有太深入,仅限于使用。
Block的作用主要有三种:
1、做为函数参数
2、反向传值
3、循环引用
现在,切入正题,block的简单使用
首先,我们来定义一个简单的block
int (^FirstBlock)(int a, int b) = ^(int a, int b){
return a+b;
};
NSLog(@"%d",FirstBlock(10,20)) ;
解析一下,看下图(好像有点乱)
通常其他的block都是在这个基础上变形的,可以有返回参数,可以没有返回参数,可以传参,也可以不传参,如下:
void (^FirstBlock)(int a, int b) = ^(int a, int b){
//Do Something
};//没有返回值
int (^FirstBlock)() = ^(){
return 10;
};//不能传参数
NSLog(@"%d",FirstBlock()) ;
这些都是简单一些的使用,下面讲解一下怎么在两个控制器之间进行回调,我们有两个控制器,一个是ViewController,一个是NextViewController,我们在NextViewController.h中定义一个block,在NextViewController.m中实现
#import <UIKit/UIKit.h>
@interface NextViewController : UIViewController
typedef void(^ChangeColor)(UIColor *color);
@property (nonatomic, strong) ChangeColor changeColor;
@end
#import "NextViewController.h"
@interface NextViewController ()
@end
@implementation NextViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 110, 100, 50)];
btn.backgroundColor = [UIColor redColor];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
}
- (void)btnClicked{
self.changeColor([UIColor redColor]);
[self.navigationController popViewControllerAnimated:YES];
}
我们在ViewController中使用
#import "ViewController.h"
#import "NextViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 100, 100, 50);
btn.backgroundColor = [UIColor grayColor];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
}
- (void)btnClicked{
NextViewController *nextVC = [[NextViewController alloc] init];
__weak typeof(self) weakSelf = self;
nextVC.changeColor = ^(UIColor *color) {
weakSelf.view.backgroundColor = color;
};
[self.navigationController pushViewController:nextVC animated:YES];
}
这样就简单实现了一个界面颜色更改的回调,感觉使用block比代理要方便一些。
最近在封装MJRefresh,又发现了一个实用block的好处,比方说,我们只是需要记录一个状态,然后我们就可以直接在方法中直接定义一个空的block,然后在需要的地方使用就可以了,也不需要使用typedef提前定义,示例:
- (void) startRefreshWithUITableView:(UIScrollView *)scrollView andHeader:(void(^)())header;//(void(^)())这里就是一个最简单的block
实现方法:
MJRefreshGifHeaderRewrite *mj_header = [MJRefreshGifHeaderRewrite headerWithRefreshingBlock:^{
header();//这里存储了 headerWithRefreshingBlock:这个block的执行状态
}];
在其他类中的使用:
[self startRefreshWithUITableView:self.tableview andHeader:^{
//do something
// 和MJ Refresh中headerWithRefreshingBlock:使用相同
}];
这是我在封装MJRefresh的DIY时用到的方法,需要MJRefresh Demo的可以去这个地方下载看一下:
https://github.com/houcj/CJ_MJRefresh
我们在封装网络请求的时候也经常会使用block进行传值,基本逻辑和我上面写的回调基本是一样的,这里就不再赘述了,有什么问题,可以留个言,帮助到你记得喜欢呦。
小知识:我们有时候需要在block块里面修改属性值,但是我们直接修改是会报错的,如下:
但是有时候,我们还是需要在block中修改数据的,这要怎么办呢?不要着急,有一个修饰叫__block ,当我们需要修改某个对象的时候,可以在前面作下修饰,如下:
搞定,perfect!