教你爱上Block(闭包)

来源:互联网 发布:java判断图片尺寸 编辑:程序博客网 时间:2024/05/01 11:51

block定义

// 定义返回类型 (^block名字)(参数类型) = ^(参数){    代码}

简单用法

定义了Block代码块之后,就可以将一整块代码当做一个变量来使用,变量可为局部变量,也可为全局变量,这也是我认为Block最方便之处。

假设要生成两个数组,一个装有5个随机数,一个装有10个随机数,将生成随机数的方法定义为一个闭包,在后文既可直接访问,如

NSNumber *(^randArray)(void) = ^{      int rand = arc4random() % 100;      NSNumber *number = [NSNumber numberWithInt:rand];      return number;  };  NSMutableArray *array1 = [[NSMutableArray alloc] init];  NSMutableArray *array2 = [[NSMutableArray alloc] init];  for (NSInteger index = 0; index<10; index++) {      [array1 addObject:randArray];  }  for (NSInteger index = 0; index<5; index++) {      [array2 addObject:randArray];  }

回调

下面给出一 tableViewCell 上按钮事件回调的例子,这个也是很多人头痛的问题,通过block可以很方便地实现,而且层次非常清晰。

自定义cell命名为 blockCell ,cell上放一 switch 控件,我们希望switch被点击时在 viewController 中可以得到switch的状态,获取到点击事件。

在 blockCell.h 中定义一 Block

typedef void(^switchAction)(blockCell *);@property (nonatomic,copy)switchAction action;

在switch的点击时间事件中调用 switchAction

blockCell.m
- (IBAction)switchToggle:(id)sender {    self.action(self);}

在 viewController 中使用这个自定义Cell对table进行初始化

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{  NSString *cellID = @"blockCell";  blockCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];  cell.action = ^(blockCell *cell){    // 既可取到行,也可取到switch状态    NSLog(@"行数:%ld, switch state: %u", (long)indexPath.row, cell.switchBtn.on);  };  return cell;}

Block封装

现在很多流行地第三方库都将回调改成了Block,之前用的Delegate特别得心应手有木有,都封装好了直接调用得到我要的结果,好了,都改成Block,不知道如何去接Block的返回值,只能一遍又一般地重写。

其实要封装很容易,将第三方库返回的Block,以一个Block来接住再返回调用的页面就可以了,本想介绍

AFNetworing 后再讲这个,但是我看了下, github 上他们的主页的readMe写得超级清楚详细,想要了解的童鞋请仔细看下他们的 readMe

添加方式

Github地址: https://github.com/AFNetworking/AFNetworking

可以将类库拷贝到工程目录下添加,推荐用 cocoapods 安装,方便更新,而且不用手动导入framework,一键设置

封装

目的:将参数传递后调用对应的方法直接得到网络返回值

新建一个类 WebRequest ,此处写一个示例,大家自己参考

#import <Foundation/Foundation.h>#import "AFNetworking.h"@interface WebRequest : NSObject-(void)requestNameWithID:(NSString *)ID WithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject, NSDictionary *myData))success  failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;@end@implementation WebRequest-(void)requestNameWithID:(NSString *)ID WithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject, NSDictionary *myData))success  failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure{    NSURL *url = [NSURL URLWithString:@"用ID拼接地接口地址"];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {        NSDictionary *dic = responseObject[@"someKey"];        success(operation, responseObject, dic);// 此处将网络返回值传递给我们自己定义的Block中的三个返回值,dic可以自定义,也可不加,如此可以返回经自己在这里已经处理好的对象,而不必调用一次,处理一次    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        failure(operation,error);// 与方法定义中的Block一致    }];}@end

调用

WebRequest *request = [[WebRequest alloc] init];[request requestNameWithID:@"123" WithSuccess:^(AFHTTPRequestOperation *operation, id responseObject, NSDictionary *myData) {  // 在网络成功时在这里就可以得到返回值了} failure:^(AFHTTPRequestOperation *operation, NSError *error) {  // 网络失败回调}];

示例工程下载

芳仔说:

现在越来越多地库使用Block, ^ 作为 Block 的标志,初看会很不适应,而且在未使用的情况下会对其有抵触心理

iOS8也有相当多的Block操作,Block出现已经有两年多了,正如日中天,取代delegate 也不远了,相信大家再稍微探究使用后会爱上它的,祝大家好运!

我建的QQ交流群:130283564,欢迎半年以上经验iOS开发者加入,加群请写一句OC验证,或注明开源中国

0 0
原创粉丝点击