关于Block之前有一篇文章已经写过一篇文章Object-C-代码块Block回顾,不过写的比较浅显,不能体现出Block在实际开发中的重要性,关于Block的基础知识,可以参考之前的博客。在实际开发中Block在回调过程中的是非常适合开发使用,不管是苹果的官方的接口还是一些第三方库的接口中都用到了Block回调。很多情况下Block和GCD一起使用,最常见的场景的就是App去后台取数据的过程中是需要时间,数据取成功之后我们才能更新UI页面,这就是最常见的回调的方式,也可以通过Notification来做,如果是单个用Notification没问题,如果请求比较多的情况的,代码量会上一个级别。

Block回调

简单的Block写法,返回类型  Block名称  参数,基本上符合方法的写法,先看一个最简单的Block写法:

    int  (^blockDemo)(int a,int b)=^(int a,int b){
return a+b;
}; NSLog(@"BlockDemo的结果:%d",blockDemo(90,72));

最后的结果是162,简单明了,很容易看懂,现在我们先通过UITableView展示后台数据,效果如下:

ViewController中的代码,简单的实现了一下UITableView:

- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc]
initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds) - 10,
CGRectGetHeight(self.view.bounds) - 64)
style:UITableViewStylePlain];
_tableView.rowHeight = 40.0;
_tableView.sectionHeaderHeight = 0.0;
_tableView.sectionFooterHeight = 0.0;
_tableView.dataSource = self;
_tableView.delegate = self;
}
return _tableView;
} -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.dataSource count];
} -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell=[[UITableViewCell alloc]init];
cell.textLabel.text=[self.dataSource objectAtIndex:indexPath.row];
return cell;
}

通过FEDataService中的fetchData取出数据:

-(NSMutableArray *)fetchData{
NSMutableArray *mutableArray=[[NSMutableArray alloc]initWithObjects:@"博客园",@"FlyElephant",@"http://www.cnblogs.com/xiaofeixiang",@"iOS技术交流群:228407086",nil];
return mutableArray;
}

Controller中的调用:

    self.dataService=[[FEDataService alloc]init];
self.dataSource=[self.dataService fetchData];

当时从后台取数据是需要时间的,而且网络不一定能取出数据,这个时候就可以通过Block进行回调,在DataService中重新定义了一个fetchDataSource方法:

-(void)fetchDataSource:(void(^)(NSMutableArray *array,NSError *error))fetchDataBlock;

注意这里的Block传参的写法,fetchDataBlock相当于是参数名,前面的是类型,实现中加入了GCD

-(void)fetchDataSource:(void (^)(NSMutableArray *, NSError *))fetchDataBlock{
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*(int64_t)1.0);
dispatch_after(time,dispatch_get_main_queue() , ^{
NSMutableArray *mutableArray=[[NSMutableArray alloc]initWithObjects:@"博客园",@"FlyElephant",@"http://www.cnblogs.com/xiaofeixiang",@"iOS技术交流群:228407086",nil];
fetchDataBlock(mutableArray,nil);
}); }

Controller中进行回调同样实现以上效果:

    [self.dataService fetchDataSource:^(NSMutableArray  *array,NSError *error){
if (!error) {
self.dataSource=array;
[self.tableView reloadData];
}
}];

Block延伸

1.栈块,堆块和全局块

定义一个块的时候,其所占的内存区域是在栈中的,块只在定义它的那个范围有有效,我们可以先看一下下面的写法:

    NSString  *string=@"博客园FlyElephant";
void (^block)();
if ([string isEqualToString:@"iOS技术交流群:228407086"]) {
block=^{
NSLog(@"keso");
};
}else{
block=^{
NSLog(@"http://www.cnblogs.com/xiaofeixiang");
};
}

先定义了block,之后在判断语句中对block进行赋值,最终栈中保存两个块的内存,在判断语句之外调用block有可能会把分配给块的内存覆盖,最终造成的结果就是有的时候正确,被覆写的时候就会造成程序崩溃,解决上面问题的方式我们可以通过block从栈内存中通过copy存储在堆内存中,代码如下:

    NSString  *string=@"博客园FlyElephant";
void (^block)();
if ([string isEqualToString:@"iOS技术交流群:228407086"]) {
block=[^{
NSLog(@"keso");
} copy];
}else{
block=[^{
NSLog(@"http://www.cnblogs.com/xiaofeixiang");
} copy];
}

存储在堆中的块就变成了引用计算类型,当引用计数变成0在ARC的环境下的就会被系统回收,而栈中的内存是由系统自动回收的,所以第一段代码稳定性不能保证,还有一种是全局块,将全局块声明在全局内存中,编译期就已经确定,不需要每次用到的在栈中创建,全局块的拷贝是一个空操作,所以全局块不可能被系统回收。

2.通过typedef简化代码可读性

Block回调中我们发现传入一个块的对象写法有的时候看起来实在不是那么简单明了,我们可以通过typedef简化定义一个块:

typedef void  (^FetchBlock)(NSMutableArray  *dataSouce,NSError  *error);

DataService中方法就可以简化了不少:

-(void)fetchDataSourceSimple:(FetchBlock)block;

实现代码和之前的block实现一样:

-(void)fetchDataSourceSimple:(FetchBlock)block{
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*(int64_t)1.0);
dispatch_after(time,dispatch_get_main_queue() , ^{
NSMutableArray *mutableArray=[[NSMutableArray alloc]initWithObjects:@"博客园",@"FlyElephant",@"http://www.cnblogs.com/xiaofeixiang",@"iOS技术交流群:228407086", nil];
block(mutableArray,nil);
});
}

行笔匆匆,难免遗漏,如有不当,多多指教~

iOS开发-Block回调的更多相关文章

  1. iOS开发--Block

    iOS开发--Block 1.什么是Block,block 的作用 ui开发和网络常见功能实现回调,按钮的事件处理方法是回调方法以及网络下载后的回调处理 (1)按钮 target-action   一 ...

  2. iOS开发——Block详解

    iOS开发--Block详解 1. Block是什么 代码块 匿名函数 闭包--能够读取其他函数内部变量的函数 函数变量 实现基于指针和函数指针 实现回调的机制 Block是一个非常有特色的语法,它可 ...

  3. ios开发 block语句块

    ios开发 block语句块 1.block 理解为匿名函数 2.block变量的定义 //定义block变量,^表示定义block //技巧:函数名左右加括号,在函数名前面在加^ void (^bl ...

  4. IOS开发 Block的学习

    苹果公司正在大力推广Block块语法的使用,据说Block会迟早取代一般协议代理的使用. Block最大的作用是函数回调,简化代码. 在ios中,将blocks当成对象来处理,它封装了一段代码,这段代 ...

  5. iOS开发Block的使用

    Block 是从 iOS4引入的,在日常开发中,会经常用到Block.特别是在多线程中,Block的用处更广泛.而且,Block不仅可以接收参数,其本身也可以作为参数,因此,Block的功能非常强大. ...

  6. iOS开发-block使用与多线程

    Block Block封装了一段代码,可以在任何时候执行 Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值. 苹果官方建议尽量多用block.在多线程.异步任务.集合遍历. ...

  7. iOS开发 -------- Block技术中的weak - strong

    一 Block是什么? 我们使用^运算符来声明一个Block变量,而且在声明完一个Block变量后要像声明普通变量一样,后面要加; 声明Block变量 int (^block)(int) = NULL ...

  8. IOS开发Block详细用法

    Block简介:       ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数 ...

  9. iOS开发——Block使用小结

    Block语法看上去好像很特别,但它实际上是作为极普通的C语言源代码处理的.Block的实质,就是Objective-C的对象. 1.Block的语法 ^ 返回值类型 参数列表 表达式 可省略返回值类 ...

随机推荐

  1. Xamarin iOS教程之自定义视图

    Xamarin iOS教程之自定义视图 Xamarin iOS自定义视图 工具栏中的视图在实际应用开发中用的很多,但是为了吸引用户的眼球,开发者可以做出一些自定义的视图. [示例2-33]以下将实现一 ...

  2. curl请求指定host ip(指定域名解析的内网某ip)

    域名www.test.com解析内部多台ip $httpHeader = array('Host: www.test.com');$url = "10.17.2.245/xxx/xxx/t. ...

  3. 使用 IntraWeb (4) - 页面布局之 TIWRegion

    TIWRegion 是容器, 首先布局好它(们). 在空白窗体上添加 4 个 TIWRegion, 然后: uses System.UITypes; //为使用 Anchors 属性 {下面代码中的设 ...

  4. IAR EWARM 关闭纯汇编函数的警告的方法

    /关闭警告 #pragma diag_suppress=Pe940 uint8_t GetMyData(void) { asm(“MOV R0, #0x550F”); } //恢复警告 #pragma ...

  5. Answer Sheet - Both, Either & Neither

    http://www.usingenglish.com/quizzes/answers.php?quiz_id=44 This page displays the answers to the 'Bo ...

  6. [golang 易犯错误] golang 局部变量初始化:=的陷阱

    我们知道,golang中局部变量初始化方法(使用“:=”创建并赋值),让我们在使用变量时很方便.但是,这也是易犯错误的地方之一.特别是这个初始化符还支持多个变量同时初始化,更特别的是它还支持原有变量赋 ...

  7. delphi CreateAnonymousThread 匿名线程

    引用  http://www.cnblogs.com/del/archive/2011/05/18/2049913.html 先看一个非多线程的例子, 代码执行时不能进行其它操作(譬如拖动窗体): { ...

  8. Team Foundation Server (TFS) 2015 安装指导

    1. 概述 微软于8月6日发布了大家期待已久的TFS 2015正式版, https://www.visualstudio.com/en-us/news/tfs2015-vs.aspx ,新版本包含的大 ...

  9. ASP.NET Web API实践系列01,以ASP.NET Web Form方式寄宿

    创建一个空的ASP.NET Web Form项目. 右键项目,添加新项,创建Web API控制器类,TestController. 删除掉TestController默认的内容,编写如下: using ...

  10. lastlog

    [root@li739-39 ~]# lastlogUsername Port From Latestroot pts/1 183.15.253.245 Thu Oct 29 05:57:29 +00 ...