block就是一段语句组成的代码段,能够认为整个block里面就是一句代码,能够有参数和返回值。能够看看下面几种常见的状况。数组
这里是打印系统时间的一个例子网络
//无参数,无返回值的block void (^logTime)(void)=^{ NSLog(@"time is ==%@",[NSDate date]); }; //调用block logTime(); /* print time is ==2016-05-21 02:13:08 +0000 */
获取当前时间的例子app
//不带参数,有返回值 NSDate* (^getNowDate)(void)=^{ return [NSDate date]; }; NSDate *nowDate=getNowDate(); NSLog(@"nowDate==%@",nowDate); // print nowDate==2016-05-21 02:43:24 +0000
打印传入的参数ide
//有参数,无返回值的block void (^logInput)(NSString *input)=^(NSString *input){ NSLog(@"input==%@",input); }; //调用logInput logInput(@"abc"); // print input==abc
对传入参数乘以7函数
//有参数,有返回值 int (^multiplierBy7)(int)=^(int multiplier){ return multiplier*7; }; int result= multiplierBy7(3); NSLog(@"result==%i",result); // print result==21
传入4个参数的状况,计算立方体的体积this
//有多个参数,有返回值的block double (^calculateCubicVolume)(double ,double ,double ,NSString *)=^(double length,double width,double height,NSString *cubicName){ double volume=length*width*height; NSLog(@"cubic name==%@",cubicName); return volume; }; //调用block double volume1=calculateCubicVolume(1,2,3,@"cubic demo 1"); NSLog(@"volume==%f",volume1); /* print cubic name==cubic demo 1 volume==6.000000 */
做为函数的参数atom
定义函数spa
void testFunction(int i1,void(^actionBlock)(int)){ if (actionBlock) { actionBlock(i1); NSLog(@"in function i1==%i",i1); } }
调用函数.net
testFunction(1024, ^(int i2) { NSLog(@"use function i2 ==%i",i2); }); /* print use function i2 ==1024 in function i1==1024 */
__block BOOL found = NO; NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma", @"X", nil]; NSString *string = @"gamma"; [aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) { *stop = YES; found = YES; } }]; // At this point, found == YES
直接声明做为属性的blockcode
//声明block类型的属性 #import "HBTestBlock.h" @interface HBTestBlock () @property(nonatomic, copy) UIView *(^viewGetter)(NSString *imageName); //注意其返回类型为UIView * @end //在另外一个类中调用 HBTestBlock *objPropertyBlockObj = [[HBTestBlock alloc] init]; objPropertyBlockObj.viewGetter = ^(NSString *imageName){ // return [[UIView alloc] init]; //特别注意此处,若对象不匹配,则会报错,设置为nil也会报错。 return [self currentView]; }; objPropertyBlockObj.viewGetter(@"hello"); //实际执行block
经过typedef 简化定义的过程
#import "ViewController.h" typedef int(^compareBlock)(int a, int b); @interface ViewController () //声明属性的block //使用简化方式的定义 @property (nonatomic,copy) compareBlock compare1; //使用基本方式进行定义 @property (nonatomic,copy) int (^compare2)(int a,int b); //void类型block 属性的定义 @property (nonatomic,copy) void (^networkFailure)(NSError *error); //对象类型的block属性的定义 @property (nonatomic,copy) UIView *(^getAView)(NSString *imageName); @implementation ViewController -(void)viewDidLoad{ //赋值属性的block self.compare1=^(int a,int b){ NSLog(@"compare1 a==%d,b==%d,result==%@",a,b,a>b?@"a>b":@"a<=b"); return a>b; }; self.compare2=^(int a,int b){ NSLog(@"compare2 a==%d,b==%d,result==%@",a,b,a>b?@"a>b":@"a<=b"); return a>b; }; //执行属性的block,这里没有接收返回值 if (self.compare1) { self.compare1(5,6); } if (self.compare2) { self.compare2(5,6); } } @end /* print 打印结果 compare1 a==5,b==6,result==a<=b compare2 a==5,b==6,result==a<=b */
对某些常常变化的部分代码作封装
由于block的调用和实现是分开的,因此能够处理一些变化的代码。好比数组中作筛选的条件就能够是一个bool返回类型的block,或者对数组进行排序的场景中,返回2个元素的顺序的代码用block实现,这样就有了很大的灵活性。
下面就举一个数字排序的例子
/** * 排序的方法 * * @param numberArray 输入的数组 * @param comparator 比较2个数字大小的block * * @return 返回排序后的数组 */ -(NSArray *)sortNumberWithNumberArray:(NSArray *)numberArray comparatorBlock:(BOOL(^)(NSNumber *,NSNumber *))comparator{ /** * 存放排序前的数组 */ NSMutableArray *beforeSort=numberArray.mutableCopy; /** * 存放排序后的数组 */ NSMutableArray *afterSort=[NSMutableArray array]; //每次循环肯定第j+1个最大的数字 for (int j=0; j<numberArray.count; j++) { //假设第一个元素就是最大的结果 NSNumber *maxNumber=[beforeSort firstObject]; for (int i=0; i<beforeSort.count; i++) { NSNumber *numberIndex=beforeSort[i]; //用比较大小的block进行比较,其实这里并不知道block的内容,只是肯定了block的返回值和参数。后续调用的时候,能够进行多种条件的实现 BOOL largerThanPreviousMax= comparator(numberIndex,maxNumber); //若是遇到一个比以前最大数字还大的数字,那就把当前最大的数字放在maxNumber里面 if (largerThanPreviousMax==YES) { maxNumber=numberIndex.copy; } } //将取到的第j+1个数移出排序前数组,放入排序后数组 [beforeSort removeObject:maxNumber]; [afterSort addObject:maxNumber]; } return afterSort.copy; }
调用的时候,定义了2个不一样的场景,按照数字的整数大小排列,以及按照绝对值大小进行排序
//排序前的数组 NSArray *array=@[@1,@(-2),@3,@(-9),@4,@8]; //根据数值的大小进行排序 BOOL (^comparator)(NSNumber*,NSNumber*)=^(NSNumber *num1,NSNumber *num2){ BOOL result=[num1 integerValue]>[num2 integerValue]; return result; }; NSArray *resultArray=[self sortNumberWithNumberArray:array comparatorBlock:comparator]; NSLog(@"resultArray%@",resultArray); /* print resultArray( 8, 4, 3, 1, "-2", "-9" ) */ //根据绝对值的大小进行排序 BOOL (^absoluteSortComparator)(NSNumber *,NSNumber *)=^(NSNumber *num1,NSNumber *num2){ BOOL result=fabs([num1 doubleValue])>fabs([num2 doubleValue]); return result; }; NSArray *absoluteSortArray=[self sortNumberWithNumberArray:array comparatorBlock:absoluteSortComparator]; NSLog(@"absoluteSortArray%@",absoluteSortArray); /* print absoluteSortArray( "-9", 8, 4, 3, "-2", 1 ) */
block传值的应用场景介绍
有2个控制器,A控制器显示一个问题,你最喜欢的数字是哪一个?点了选择之后就跳转到B控制器,在B控制器有一个列表,能够供用户选择。需求就是在B中选择了之后,A中作出相应的修改。
接下来就上代码了
首先是第一个页面
.h
#import <UIKit/UIKit.h> @interface FavouriteNumberViewController : UIViewController @end
.m
// // FavouriteNumberViewController.m // BlockPassValue // // #import "FavouriteNumberViewController.h" #import "ChoosingFavouriteNumberViewController.h" @interface FavouriteNumberViewController () @property (nonatomic,weak) UILabel *favouriteNumberLabel; @end @implementation FavouriteNumberViewController - (void)viewDidLoad { [super viewDidLoad]; UILabel *favouriteNumberLabel=[[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 100)]; favouriteNumberLabel.font=[UIFont systemFontOfSize:13.0]; favouriteNumberLabel.backgroundColor=[UIColor greenColor]; [self.view addSubview:favouriteNumberLabel]; self.favouriteNumberLabel=favouriteNumberLabel; UIButton *pickNumberButton=[[UIButton alloc]initWithFrame:CGRectMake(100, 200, 200, 100)]; [pickNumberButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [pickNumberButton setTitle:@"点击选择数字" forState:UIControlStateNormal]; [pickNumberButton addTarget:self action:@selector(pickupNumber) forControlEvents:UIControlEventTouchUpInside]; pickNumberButton.backgroundColor=[UIColor orangeColor]; [self.view addSubview:pickNumberButton]; // Do any additional setup after loading the view. } -(void)pickupNumber{ ChoosingFavouriteNumberViewController *choosingNumberVC=[[ChoosingFavouriteNumberViewController alloc]init]; __weak typeof (self) weakSelf=self; choosingNumberVC.chooseNumberBlock=^(NSString *number){ weakSelf.favouriteNumberLabel.text=[NSString stringWithFormat:@"最喜欢的数字是%@",number]; }; [self.navigationController pushViewController:choosingNumberVC animated:YES]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end
.h
#import <UIKit/UIKit.h> typedef void (^ChooseNumberBlock) (NSString *number) ; @interface ChoosingFavouriteNumberViewController : UIViewController @property (nonatomic,copy) ChooseNumberBlock chooseNumberBlock; @end
.m
// // ChoosingFavouriteNumberViewController.m // BlockPassValue // // #import "ChoosingFavouriteNumberViewController.h" @interface ChoosingFavouriteNumberViewController () <UITableViewDataSource,UITableViewDelegate> @property (nonatomic,weak) UITableView *tableView; @property (nonatomic,strong) NSArray *numberArray; @end @implementation ChoosingFavouriteNumberViewController #pragma mark - vc life cycle - (void)viewDidLoad { [super viewDidLoad]; self.title=@"请选择你喜欢的数字"; UITableView *tableView=[[UITableView alloc]init]; tableView.delegate=self; tableView.dataSource=self; [self.view addSubview:tableView]; tableView.frame=self.view.bounds; self.tableView=tableView; self.view.backgroundColor=[UIColor whiteColor]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - data getter -(NSArray *)numberArray{ if (!_numberArray) { NSMutableArray *numberArray=[NSMutableArray array]; for (int i=0; i<10; i++) { [numberArray addObject:[NSString stringWithFormat:@"%i",i]]; } _numberArray=numberArray.copy; } return _numberArray; } #pragma mark -table view datasource -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.numberArray.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellIdentifier=@"cellIdentifier"; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if(!cell){ cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } cell.textLabel.text=self.numberArray[indexPath.row]; return cell; } #pragma mark - table view delegate -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ //调用了以前定义的block内容 if (self.chooseNumberBlock) { NSString *selectedNumber=self.numberArray[indexPath.row]; self.chooseNumberBlock(selectedNumber); } [self.navigationController popViewControllerAnimated:YES]; } @end
block中的变量的对应管理
局部变量
全局变量
__block修饰的变量
参考资料