iOS开发-Block回调
关于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回调的更多相关文章
- iOS开发--Block
iOS开发--Block 1.什么是Block,block 的作用 ui开发和网络常见功能实现回调,按钮的事件处理方法是回调方法以及网络下载后的回调处理 (1)按钮 target-action 一 ...
- iOS开发——Block详解
iOS开发--Block详解 1. Block是什么 代码块 匿名函数 闭包--能够读取其他函数内部变量的函数 函数变量 实现基于指针和函数指针 实现回调的机制 Block是一个非常有特色的语法,它可 ...
- ios开发 block语句块
ios开发 block语句块 1.block 理解为匿名函数 2.block变量的定义 //定义block变量,^表示定义block //技巧:函数名左右加括号,在函数名前面在加^ void (^bl ...
- IOS开发 Block的学习
苹果公司正在大力推广Block块语法的使用,据说Block会迟早取代一般协议代理的使用. Block最大的作用是函数回调,简化代码. 在ios中,将blocks当成对象来处理,它封装了一段代码,这段代 ...
- iOS开发Block的使用
Block 是从 iOS4引入的,在日常开发中,会经常用到Block.特别是在多线程中,Block的用处更广泛.而且,Block不仅可以接收参数,其本身也可以作为参数,因此,Block的功能非常强大. ...
- iOS开发-block使用与多线程
Block Block封装了一段代码,可以在任何时候执行 Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值. 苹果官方建议尽量多用block.在多线程.异步任务.集合遍历. ...
- iOS开发 -------- Block技术中的weak - strong
一 Block是什么? 我们使用^运算符来声明一个Block变量,而且在声明完一个Block变量后要像声明普通变量一样,后面要加; 声明Block变量 int (^block)(int) = NULL ...
- IOS开发Block详细用法
Block简介: ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数 ...
- iOS开发——Block使用小结
Block语法看上去好像很特别,但它实际上是作为极普通的C语言源代码处理的.Block的实质,就是Objective-C的对象. 1.Block的语法 ^ 返回值类型 参数列表 表达式 可省略返回值类 ...
随机推荐
- mysql索引原理剖析
一.索引的原理 所谓索引,即是快速定位与查找,那么索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数(B+树相比B树,其非叶子节点占用更小的空间,可以有更多非叶子节点存放在再内存中,减少大量的IO ...
- 1257: [CQOI2007]余数之和
题目链接 bzoj1257: [CQOI2007]余数之和 题解 数论分块,乘等差数列求和 代码 #include<bits/stdc++.h> using namespace std; ...
- BZOJ3616 : War
对每个点维护一个bitset,记录哪些点可以攻击它. 可以通过kd-tree+标记永久化实现. 对于一个阵营,它在m轮之后防御系统全部完好的概率为$(1-\frac{攻击它的点数}{n})^m$. 时 ...
- 【学习笔记】python的代码块(吐槽)
曾经我以为python是像pascal那样begin开始end结束, 直到今天…… 我才知道python是用缩进作为代码段标识的…… >>> def test(n): ... if ...
- .net加载失败的程序集重新加载
在.net程序中,程序集是Lazy加载的,只有在用的时候才会去加载,当程序集加载失败时,会触发AppDomain.AssemblyResolve的事件,在这个事件中,我们甚至还可以进行补救,从别得地方 ...
- bash 脚本中分号的作用
在Linux bash shell中,语句中的分号一般用作代码块标识 1.单行语句一般要用到分号来区分代码块.比如: weblogic@pmtest:/$if [ "$PS1" ] ...
- C#面向服务WebService从入门到精通
<C#面向服务WebService从入门到精通>包含以下两个部分: 一.<C#远程调用技术WebService修炼手册[基础篇]>本次分享课您将学习到以下干货知识点:1).We ...
- [Bug]Unable to start process dotnet.exe
This morning I did a sync of a repo using of Visual Studio and then tried to run a web application I ...
- mybatis学习之路----批量更新数据两种方法效率对比
原文:https://blog.csdn.net/xu1916659422/article/details/77971696/ 上节探讨了批量新增数据,这节探讨批量更新数据两种写法的效率问题. 实现方 ...
- Struts2标签的<s:set>标签与JSTL的<c:set>标签
<s:set>标签 set标签 用于将某个值放入指定范围内.例如application.session范围等. 当某个值所在的对象图深度非常深时,例如如下:person.worker.wi ...