文档章节

block的基本语法和应用

云飞扬v5
 云飞扬v5
发布于 2016/05/21 12:00
字数 1797
阅读 45
收藏 2

代码片段block基本语法

block就是一段语句组成的代码段,可以认为整个block里面就是一句代码,可以有参数和返回值。可以看看下面几种常见的情况。

不带参数无返回值

这里是打印系统时间的一个例子

   //无参数,无返回值的block
    void (^logTime)(void)=^{
        NSLog(@"time is ==%@",[NSDate date]);
    };
    
    //调用block
    logTime();
    
    /*
     print time is ==2016-05-21 02:13:08 +0000

     
     */

不带参数有返回值

获取当前时间的例子

  //不带参数,有返回值
    NSDate* (^getNowDate)(void)=^{
        return [NSDate date];
    };
    
    NSDate *nowDate=getNowDate();
    NSLog(@"nowDate==%@",nowDate);
//    print nowDate==2016-05-21 02:43:24 +0000

 

带参数无返回值

打印传入的参数

   //有参数,无返回值的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个参数的情况,计算立方体的体积

    //有多个参数,有返回值的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
     */

 

作为函数的参数

 

定义函数

void testFunction(int i1,void(^actionBlock)(int)){
    if (actionBlock) {
        actionBlock(i1);
        NSLog(@"in function i1==%i",i1);
    }
}

 

调用函数

   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

 

 

作为属性

直接声明作为属性的block

  
//声明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

 

 

© 著作权归作者所有

共有 人打赏支持
云飞扬v5
粉丝 11
博文 105
码字总数 67465
作品 0
金华
【javac添加python 列表特性10】为Block添加返回值

前面几篇提到的一些特性,都是通过把特殊的新语法,翻译成java可以支持的语法来实现的。javac编译一个文件的过程为:(参见javac编译文件过程) Scanner->Parser->Annotation(optional)->Ent...

guoliang
2013/01/08
0
0
(一)Block的实质初探

相关文章 (一)Block的实质初探 (二)Block之存储域 NSConcreteStackBlock,NSConcreteGlobalBlock,NSConcreteMallocBlock (三)Block之截获变量和对象 (四)Block之 _block修饰符及其存...

madaoCN
2017/10/21
0
0
Block作为属性、方法参数、返回值

简介: 首先来概述一下,Block对象提供了一个 特别的(ad hoc)函数,这个函数是使用C和C派生语言(如Objective-C和C++)来创建的一个表达式,Block对象在其他语言和环境中有时候可以理解为一...

吃粑粑的毕教授
2017/10/07
0
0
Pug+Stylus+Bootstrap入门

本文说明 博主最近在学习Express.js,里面涉及到Pug,Stylus和Bootstrap的使用。为了使文章主题专一,故而把有关这三者的基本知识点另外写成本文。 本文在写作过程中主要参阅了下面这些资料:...

桥头堡2015
2016/04/13
963
0
01 - Object-C入门

Object-C简介 在C语言的基础之上,增加了一层最小的面向对象语法 完全兼容C语言 oc代码中可以混合使用C语言和C++代码 oc可以用来开发MAC OS X平台和 ios平台的应用程序 基本语法 关键字 基本...

口十耳
2015/12/22
59
0

没有更多内容

加载失败,请刷新页面

加载更多

VSCode 搭建Vue开发环境之Vue CLI

一、简介说明 1.关于VS Code开发工具,安装和配置,更多可以参考以前文章 2.关于Vue.js,Vue是一个优秀的渐进式前端框架,不仅易于上手,还便于与第三方库或既有项目整合。 3.关于Vue是使用方...

tianma3798
23分钟前
2
0
MySQL 相关博客整理

1. 《深入理解 MySQL 底层实现》 简评:文章从硬盘底层存储原理讲解到MySQL存储原理,其中涉及InnoDB 和 Myisam 中 B+Tree 的应用,以及常见数据库优化思路,算是一片很不错的讲解MySQL原理的...

科陆李明
33分钟前
2
0
pada rabbitmq server mangage

查看配置文件 ubuntu@node4:/etc/rabbitmq$ lltotal 28drwxr-xr-x 2 rabbitmq rabbitmq 4096 Jun 6 13:52 ./drwxr-xr-x 104 root root 12288 Sep 26 11:39 ../-rw-r--r-- ......

qwfys
41分钟前
0
0
SpringBoot进阶

慕课网链接 表单数据的验证 在pojo类属性的上面添加注解 @Entitypublic class Girl { @Id @GeneratedValue private Integer id; @NotBlank(message = "这个字段...

踏破铁鞋无觅处
48分钟前
1
0
【SylixOS】QT-QWS流程介绍

QWS简介 QWS(QT Windows System)是QT自行开发的窗口系统,体系结构类似X Windows的C/S结构。QWS Server在物理设备上显示,QWS Client实现界面,两者通过socket进行彼此的通讯。在很多嵌入式系...

suokin
48分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部