Block的使用

2015-05-21  本文已影响66人  Ray_win

现在的无论是框架还是项目中,越来越多的使用block代码块。
个人觉得:第一可以使代码看起来更简单明了,第二可以取代以前的delegate使代码的逻辑看起来更清晰。

借一张图表达基本定义:

(1)最基础的用法案例,可以把block理解为一段类似变量一样的可执行函数代码片段:

  • void (^printBlock)(NSString *x);    
  • printBlock = ^(NSString* str)    
  • {    
  •     NSLog(@"print:%@", str);    
  • };    
  • printBlock(@"hello world!");    
  • (2)由于是变量,所以比方法等可以更灵活的使用,因为可以把block当做一个变量传入到另一个方法。

  • - (void)viewDidLoad {  
  •     [super viewDidLoad];  
  •     NSLog(@"我在玩手机");  
  •     NSLog(@"手机没电了");  
  •     [self chargeMyIphone:^{  
  •         NSLog(@"去逛街");  
  •     }];  
  •     NSLog(@"我在看电视");  
  • }  
  • -(void)chargeMyIphone:(void(^)(void))finishBlock {  
  •     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(110 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{  
  •         NSLog(@"电充好了");  
  •         finishBlock();  
  •     });  
  • }  
  • (3)上述方法是在单个类中执行的,如果在两个类中使用就能更加显现出其功能。可以用来取代代理,可以是逻辑变得清晰。如此处模拟一个发送HTTP请求的类。

  • #import <Foundation/Foundation.h>  
  •   
  • typedef void(^HttpSendBlock)(NSDictionary *dict);  
  •   
  • @interface HttpReq : NSObject  
  •   
  • -(void)sendHttpReqUseUrl:(NSString*)url withBlock:(HttpSendBlock) block;  
  •   
  • @end  
  • #import "HttpReq.h"  
  •   
  • @implementation HttpReq  
  •   
  • -(void)sendHttpReqUseUrl:(NSString*)url withBlock:(HttpSendBlock) block{  
  •     //……………发送请求并获取返回结果……………  
  •     NSDictionary *dic = [[NSDictionary alloc]initWithObjects:[NSArray arrayWithObjects:@"name",@"state", nil nil] forKeys:[NSArray arrayWithObjects:@"wdl",@"ok", nil nil]];  
  •     //返回请求结果  
  •     block(dic);  
  • }  
  •   
  • @end  
  • 在一个Controller调用发送HTTP请求。

  • - (void)viewDidLoad {  
  •     [super viewDidLoad];  
  •     HttpReq *req = [[HttpReq alloc]init];  
  •     [req sendHttpReqUseUrl:@"www.baidu.com" withBlock:^(NSDictionary *dict) {  
  •         NSLog(@"dict : %@",dict.description);  
  •     }];  
  • }  
  • 看起来比较清晰,如果使用delegate的形势就相对比较繁琐一些,需要定义@optional,需要引用代理,实现代理,通过代理将结果返回回来

    下面我们来看几个实例:

    1、参数是NSString*的代码块

  • void (^printBlock)(NSString *x);  
  • printBlock = ^(NSString* str)  
  • {  
  •     NSLog(@"print:%@", str);  
  • };  
  • printBlock(@"hello world!");  
  • 运行结果是:

    print:helloworld!

      2、代码用在字符串数组排序

  • NSArray *stringArray = [NSArray arrayWithObjects:@"abc 1", @"abc 21", @"abc 12",@"abc 13",@"abc 05",nil];  
  • NSComparator sortBlock = ^(id string1, id string2)  
  • {  
  •     return [string1 compare:string2];  
  • };  
  • NSArray *sortArray = [stringArray sortedArrayUsingComparator:sortBlock];  
  • NSLog(@"sortArray:%@", sortArray);  
  • 运行结果:

    sortArray:(

        "abc 05",

       "abc 1",

       "abc 12",

       "abc 13",

       "abc 21"

    )

    3、代码块的递归调用

    代码块想要递归调用,代码块变量必须是全局变量或者是静态变量,这样在程序启动的时候代码块变量就初始化了,可以递归调用

  • static void (^ const blocks)(int) = ^(int i)  
  • {  
  •     if (i > 0) {  
  •         NSLog(@"num:%d", i);  
  •         blocks(i - 1);  
  •     }  
  • };  
  • blocks(3);  
  • 运行打印结果:

    num:3

    num:2

    num:1

    4、在代码块中使用局部变量和全局变量

    在代码块中可以使用和改变全局变量

  • int global = 1000;  
  • int main(int argc, const char * argv[])  
  • {  
  •     @autoreleasepool {  
  •         void(^block)(void) = ^(void)  
  •         {  
  •             global++;  
  •             NSLog(@"global:%d", global);  
  •         };  
  •         block();  
  •         NSLog(@"global:%d", global);  
  •     }  
  •     return 0;  
  • }  
  •  运行打印结果:

    global:1001

    global:1001

    而局部变量可以使用,但是不能改变。

  • int local = 500;  
  • void(^block)(void) = ^(void)  
  • {  
  •       local++;  
  •     NSLog(@"local:%d", local);  
  • };  
  • block();  
  • NSLog(@"local:%d", local);  
  • 在代码块中改变局部变量编译不通过。怎么在代码块中改变局部变量呢?在局部变量前面加上关键字:__block

  • __block int local = 500;  
  • void(^block)(void) = ^(void)  
  • {  
  •     local++;  
  •     NSLog(@"local:%d", local);  
  • };  
  • block();  
  • NSLog(@"local:%d", local);  
  • 运行结果:local:501

    原文地址:http://blog.csdn.net/lvxiangan/article/details/43228845

    上一篇 下一篇

    猜你喜欢

    热点阅读