block的基本語法和應用

代碼片斷block基本語法

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的應用

封裝網絡請求

對某些常常變化的部分代碼作封裝

 

由於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修飾的變量

 

 

 

 

參考資料

重要經驗五:block做爲屬性的注意事項

http://blog.csdn.net/lvmaker/article/details/25468485

相關文章
相關標籤/搜索