iOS开发-Block回调

简介:

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

Block回调

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- (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取出数据:

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

Controller中的调用:

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

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

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

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

1
2
3
4
5
6
7
8
-( 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中进行回调同样实现以上效果:

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

Block延伸

1.栈块,堆块和全局块

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

1
2
3
4
5
6
7
8
9
10
11
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存储在堆内存中,代码如下:

1
2
3
4
5
6
7
8
9
10
11
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简化定义一个块:

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

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

1
-( void )fetchDataSourceSimple:(FetchBlock)block;

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

1
2
3
4
5
6
7
-( 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 );
     });
}

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

本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4666796.html,如需转载请自行联系原作者

相关文章
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
19天前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
111 66
|
5天前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
|
29天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
1月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
2月前
|
存储 前端开发 Swift
探索iOS开发:从新手到专家的旅程
本文将带您领略iOS开发的奇妙之旅,从基础概念的理解到高级技巧的掌握,逐步深入iOS的世界。文章不仅分享技术知识,还鼓励读者在编程之路上保持好奇心和创新精神,实现个人成长与技术突破。
|
2月前
|
安全 IDE Swift
探索iOS开发之旅:从初学者到专家
在这篇文章中,我们将一起踏上iOS开发的旅程,从基础概念的理解到深入掌握核心技术。无论你是编程新手还是希望提升技能的开发者,这里都有你需要的指南和启示。我们将通过实际案例和代码示例,展示如何构建一个功能齐全的iOS应用。准备好了吗?让我们一起开始吧!
|
2月前
|
安全 Swift iOS开发
Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法
本文深入探讨了 Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法。Swift 以其简洁、高效和类型安全的特点,结合 UIKit 丰富的组件和功能,为开发者提供了强大的工具。文章从 Swift 的语法优势、类型安全、编程模型以及与 UIKit 的集成,到 UIKit 的主要组件和功能,再到构建界面的实践技巧和实际案例分析,全面介绍了如何利用这些技术创建高质量的用户界面。
34 2
|
2月前
|
vr&ar Android开发 iOS开发
安卓与iOS开发中的用户界面设计原则
【10月更文挑战第41天】探索移动应用开发的精髓,本文将深入分析安卓和iOS平台上用户界面设计的核心原则。通过比较两大操作系统的设计哲学,我们将揭示如何打造直观、易用且美观的应用程序界面。无论你是初学者还是资深开发者,这篇文章都将为你提供宝贵的见解和实用的技巧,帮助你在竞争激烈的应用市场中脱颖而出。
|
2月前
|
设计模式 Swift iOS开发
探索iOS开发:从基础到高级,打造你的第一款App
【10月更文挑战第40天】在这个数字时代,掌握移动应用开发已成为许多技术爱好者的梦想。本文将带你走进iOS开发的世界,从最基础的概念出发,逐步深入到高级功能实现,最终指导你完成自己的第一款App。无论你是编程新手还是有志于扩展技能的开发者,这篇文章都将为你提供一条清晰的学习路径。让我们一起开始这段旅程吧!