天天看点

iOS开发-Block回调

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

1

2

3

4

5

<code>int</code>  <code>(^blockDemo)(</code><code>int</code> <code>a,</code><code>int</code> <code>b)=^(</code><code>int</code> <code>a,</code><code>int</code> <code>b){</code>

<code>    </code><code>return</code> <code>a+b;</code>

<code>};</code>

<code>NSLog</code><code>(@</code><code>"BlockDemo的结果:%d"</code><code>,blockDemo(90,72));</code>

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

iOS开发-Block回调

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

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<code>- (UITableView *)tableView {</code>

<code>    </code><code>if</code> <code>(!_tableView) {</code>

<code>        </code><code>_tableView = [[UITableView alloc]</code>

<code>                      </code><code>initWithFrame:CGRectMake(0, 64, CGRectGetWidth(</code><code>self</code><code>.view.bounds) - 10,</code>

<code>                                               </code><code>CGRectGetHeight(</code><code>self</code><code>.view.bounds) - 64)</code>

<code>                      </code><code>style:UITableViewStylePlain];</code>

<code>        </code><code>_tableView.rowHeight = 40.0;</code>

<code>        </code><code>_tableView.sectionHeaderHeight = 0.0;</code>

<code>        </code><code>_tableView.sectionFooterHeight = 0.0;</code>

<code>        </code><code>_tableView.dataSource = </code><code>self</code><code>;</code>

<code>        </code><code>_tableView.delegate = </code><code>self</code><code>;</code>

<code>    </code><code>}</code>

<code>    </code><code>return</code> <code>_tableView;</code>

<code>}</code>

<code>-(</code><code>NSInteger</code><code>)tableView:(UITableView *)tableView numberOfRowsInSection:(</code><code>NSInteger</code><code>)section{</code>

<code>    </code><code>return</code> <code>[</code><code>self</code><code>.dataSource count];</code>

<code>-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(</code><code>NSIndexPath</code> <code>*)indexPath{</code>

<code>    </code><code>UITableViewCell  *cell=[[UITableViewCell alloc]init];</code>

<code>    </code><code>cell.textLabel.text=[</code><code>self</code><code>.dataSource objectAtIndex:indexPath.row];</code>

<code>    </code><code>return</code> <code>cell;</code>

通过FEDataService中的fetchData取出数据:

<code>-(</code><code>NSMutableArray</code> <code>*)fetchData{</code>

<code>    </code><code>NSMutableArray</code>  <code>*mutableArray=[[</code><code>NSMutableArray</code> <code>alloc]initWithObjects:@</code><code>"博客园"</code><code>,@</code><code>"FlyElephant"</code><code>,@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>,@</code><code>"iOS技术交流群:228407086"</code><code>,</code><code>nil</code><code>];</code>

<code>    </code><code>return</code> <code>mutableArray;</code>

Controller中的调用:

<code>self</code><code>.dataService=[[FEDataService alloc]init];</code>

<code>self</code><code>.dataSource=[</code><code>self</code><code>.dataService  fetchData];</code>

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

<code>-(</code><code>void</code><code>)fetchDataSource:(</code><code>void</code><code>(^)(</code><code>NSMutableArray</code> <code>*array,</code><code>NSError</code> <code>*error))fetchDataBlock;</code>

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

<code>-(</code><code>void</code><code>)fetchDataSource:(</code><code>void</code> <code>(^)(</code><code>NSMutableArray</code> <code>*, </code><code>NSError</code> <code>*))fetchDataBlock{</code>

<code>    </code><code>dispatch_time_t  time=dispatch_time(DISPATCH_TIME_NOW, </code><code>NSEC_PER_SEC</code><code>*(int64_t)1.0);</code>

<code>    </code><code>dispatch_after(time,dispatch_get_main_queue() , ^{</code>

<code>         </code><code>NSMutableArray</code>  <code>*mutableArray=[[</code><code>NSMutableArray</code> <code>alloc]initWithObjects:@</code><code>"博客园"</code><code>,@</code><code>"FlyElephant"</code><code>,@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>,@</code><code>"iOS技术交流群:228407086"</code><code>,</code><code>nil</code><code>];</code>

<code>        </code><code>fetchDataBlock(mutableArray,</code><code>nil</code><code>);</code>

<code>    </code><code>});</code>

<code>    </code> 

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

<code>[</code><code>self</code><code>.dataService fetchDataSource:^(</code><code>NSMutableArray</code>  <code>*array,</code><code>NSError</code> <code>*error){</code>

<code>    </code><code>if</code> <code>(!error) {</code>

<code>        </code><code>self</code><code>.dataSource=array;</code>

<code>        </code><code>[</code><code>self</code><code>.tableView reloadData];</code>

<code>}];</code>

1.栈块,堆块和全局块

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

<code>NSString</code>  <code>*string=@</code><code>"博客园FlyElephant"</code><code>;</code>

<code>void</code>  <code>(^block)();</code>

<code>if</code> <code>([string isEqualToString:@</code><code>"iOS技术交流群:228407086"</code><code>]) {</code>

<code>    </code><code>block=^{</code>

<code>        </code><code>NSLog</code><code>(@</code><code>"keso"</code><code>);</code>

<code>    </code><code>};</code>

<code>}</code><code>else</code><code>{</code>

<code>        </code><code>NSLog</code><code>(@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>);</code>

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

<code>    </code><code>block=[^{</code>

<code>    </code><code>} </code><code>copy</code><code>];</code>

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

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

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

<code>typedef</code> <code>void</code>  <code>(^FetchBlock)(</code><code>NSMutableArray</code>  <code>*dataSouce,</code><code>NSError</code>  <code>*error);</code>

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

<code>-(</code><code>void</code><code>)fetchDataSourceSimple:(FetchBlock)block;</code>

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

<code>-(</code><code>void</code><code>)fetchDataSourceSimple:(FetchBlock)block{</code>

<code>        </code><code>NSMutableArray</code>  <code>*mutableArray=[[</code><code>NSMutableArray</code> <code>alloc]initWithObjects:@</code><code>"博客园"</code><code>,@</code><code>"FlyElephant"</code><code>,@</code><code>"http://www.cnblogs.com/xiaofeixiang"</code><code>,@</code><code>"iOS技术交流群:228407086"</code><code>, </code><code>nil</code><code>];</code>

<code>        </code><code>block(mutableArray,</code><code>nil</code><code>);</code>

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

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