关于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. POJ.2774.Long Long Message/SPOJ.1811.LCS(后缀自动机)

    题目链接 POJ2774 SPOJ1811 LCS - Longest Common Substring 确实比后缀数组快多了(废话→_→). \(Description\) 求两个字符串最长公共子串 ...

  2. BZOJ4045 : [Cerc2014] bricks

    首先求出B和W的个数,如果只出现了一种那么直接输出sum(k). 否则依次扫描,能割就割,时间复杂度$O(n)$. #include<cstdio> #define N 100010 ty ...

  3. git 用户名和密码保存

    git config --global credential.helper store 输入一次后,后续不再需要输入用户名密码

  4. 使用GSON和泛型解析约定格式的JSON串(转)

    时间紧张,先记一笔,后续优化与完善. 解决的问题: 使用GSON和泛型解析约定格式的JSON串. 背景介绍: 1.使用GSON来进行JSON串与java代码的互相转换. 2.JSON的格式如下三种: ...

  5. 基于设备树的controller学习(1)

    作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.10.17 概述 在设备树中我们经常见到诸如"#clock-cells"."# ...

  6. 在ASP.NET MVC中使用Knockout实践05,基本验证

    本篇体验View Model验证.Knockout的subscribe方法能为View Model成员注册验证规则. @{ ViewBag.Title = "Index"; Lay ...

  7. NSZombie 详解 -僵尸对象

    1.什么是僵尸对象? 简而言之,就是过度释放的对象. 2.僵尸对象有什么特点? 如果一个对象a被变成了僵尸对象,那么,在进行下面的判断时,a是会被系统当成一个对象来进行判断的.但是,如果你使用a进行其 ...

  8. sqlite 字符串 转 整型 cast 函数 (强制类型转换 )

    sqlite 字符串 转 整型使用 cast 函数 语法: cast(col_name as type) 例子: 表:JobInfo 表内字段:Salary  薪水 select * from Job ...

  9. C# String.split()用法小结

    第一种方法 string s=abcdeabcdeabcde; string[] sArray=s.Split('c') ; foreach(string i in sArray) Console.W ...

  10. ibatis.net:第八天,QueryForDictionary

    xml <statement id="FindOrdersByCustomer" parameterClass="string" resultClass= ...