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修飾的變量
參考資料