如何在 iOS 5 中使用 Block

这篇文章来自 iOS 教程团队成员 Adam Burkepile, 一个全职软件咨询顾问和独立 iOS 开发者。 看看他最新的 app Pocket No Agenda , 或者在 Twitter 上面关注它。 html

欢迎回到 在 iOS 5 中使用 Block 系列教程 – 咱们已经有了一些 Storyboard/Interface Builder 方面的实践!Order up some Storyboards and Blocks in this tutorial! ios

在这个教程的第一部分,咱们用 iOS 5 中的 Storyboard 建立视图而且创建了一个很好看的界面, 和你在上边看到的那张截图差很少。 程序员

在这第二部分也是这个系列的最后一部分中,咱们要使用 Block了! 咱们将会讨论 Block 到底是什么,它们的语法, 如何使用它们, 而且包含了大量的实例。 数组

咱们将会向你展现你怎样经过 NSArray, UIView 动画,GCD 来使用 Block, 还有其余更多! 闭包

安排好你的时间,而且实践性和快乐的阅读吧。 app

 

 

开始:Block 简介

Block 是 iOS 4.0 和 Mac OSX 10.6 引入的一个新特性。 Block 能够极大的简化代码。 他们能够帮助你减小代码, 减小对代理的依赖, 而且写出更加简洁,可读性强的代码。 框架

即便有这么多好处, 仍是有不少开发者没有使用 Block, 由于他们不知道如何使用。 可是 Block 绝对是你做为一个 Objective-C 程序员,必定会想要掌握的技能。 函数

让咱们来看看 Block 是谁, 是什么,在哪里用它, 为何用它, 还有何时用它。 动画

Block 是什么东西,它为何那么重要? ui

Why do I need these fancy block things?

Why do I need these fancy block things?

Block 的核心就是一段能够在之后的时间里执行的代码。

Block 是 first-class functions, 也就是说 Block 是一个标准 Objective-C 对象。 由于他们是对象, 他们能够做为参数传递, 做为方法或函数的返回值, 赋值给变量。

在其余语言中,好比 Python,Ruby 和 Lisp, Block 又叫作闭包, 由于他们包含了定义时的状态。 Block 会为全部和它在同一做用范围内的局部变量建立一个常量拷贝。

在没有 Block 以前, 若是咱们想在以后的某个时间回调一个方法, 你通常会用代理或者 NSNotificationCenter。 这样也不错, 除了一点,它会让你的代码处处都是 – 你在一个地方开启了一个任务, 而后在另一个地方处理它的结果。

Block 是很是不错的, 由于它能将和一个任务相关的全部代码都放在一个地方, 你立刻就会看到。

 

 

Block 为谁准备?

你! Block 是为每个人准备的! 严格的说, Block 是为每一个人和每一个将要用到 Block 的人准备的。 Block 是将来的趋势, 因此你最好如今也学一下。 不少内建的方法已经用 Block 重写或者提供了接受 Block 参数的版本。

你怎样用 Block?
这张 iOS Developer Library 中的图片很好的解释了 Block 的语法:

Block 的声明格式以下:

return_type (^block_name)(param_type, param_type, ...)

 

若是你以前使用过其余 C 类型的语言,那这段代码你应该看起来很眼熟, 除了这个 ^ 符号。 ^ 这个符号表示了 “咱们定义的这个东西是一个 Block”。

若是你能分析到 ^ 符号的意思 “我是一个 Block” ,那么祝贺你 – 你已经了解了 Block 中最难的部分! :]

注意这里不须要参数的名称, 不过,若是你喜欢的话,你也能够加上它们。

下面是定义 Block 的一个例子:

int (^add)(int,int)

下面是 Block 的定义格式:

// Block Definition ^return_type(param_type param_name, param_type param_name, ...) { ... return return_type; }

这就是 Blcok 实际是怎么建立的。

 Block 还有另一种不一样的定义方法。 以 ^ 符号起始,后面跟随着参数,这里的参数必须有参数名, 还必须和它要赋值到的 Block 声明中参数列表里面的参数类型和顺序相匹配。下面是实际的代码。

当你定义 Block 时, 返回值类型是可选的,而且能够继承它里面代码的返回值类型。 若是它里面有多条 return 语句,那么这些语句返回的类型必须都是相同的 (或者强制转换到相同的类型)。

这里是 Block 定义的一个例子:

^(int number1, int number2){ return number1+number2 }

 

若是咱们将 Block 的声明和定义放在一块儿, 咱们会获得这样一个语句:

int (^add)(int,int) = ^(int number1, int number2){ return number1+number2; }

咱们能够这样使用 Block:

int resultFromBlock = add(2,2);

让咱们看一看,使用 Block 和不使用 Block 之间对比的一些例子

 

示例: NSArray

让咱们看看 Block 如何改变咱们操做数组的方式。

首先,让咱们看一下通常状况下处理循环的方式:

BOOL stop;
for (int i = 0 ; i < [theArray count] ; i++)
{
    NSLog(@"The object at index %d is %@",i,[theArray objectAtIndex:i]);
    if (stop) break;
}

上面方法中的 “stop” 变量,可能会让你不太明白。 可是若是用 Block 的方式实现它,你就会很清楚的看明白了。 Block 提供了一个 “stop” 变量能让你在任什么时候候中止循环,咱们简单的复制了这个功能来支持和 Block 的方式等同的效果。

如今,让咱们看看用快速枚举的方法实现一样的功能:

BOOL stop;
int idx = 0;
for (id obj in theArray)
{
   NSLog(@"The object at index %d is %@",idx,obj);
   if (stop)
       break;
   idx++;
}

如今,用 Block:

[theArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{ NSLog(@"The object at index %d is %@",idx,obj); }];

 

在上面这个基于 Block 的代码中,你可能会好奇 “stop” 这个变量究竟是什么。 这个变量能够在 block 中赋值为 YES, 这样就后续的任何循环都不会继续了。 这是传递到 enumerateObjectsUsingBlock 方法的 Block 中的其中一个参数。

上面这个例子有些微不足道, 并且也很难明显的体现出 Block 所到来的好处。 可是我想给你们指出 Block 的两点好处:

  1. 简单性. 使用 Block 咱们能够不写任何附加的代码就能够访问对象,对象在数组中的索引,stop 变量。 这意味着少许的代码,减小了发生编码错误的机会(固然,并不是咱们必定会出现编码错误)。
  2. 速度. 使用 Block 在执行速度上要比使用快速枚举快。 在咱们这个例子中,这点微小的速度提高不值得一提,可是在更复杂的状况下,这个优点就愈来愈重要。(来源)

 

 

示例: UIView Animation

让咱们对一个单独的 UIView 执行一个简单的动画。 它将视图的透明度调整为 0,将这个视图向下和向右移动 50 点。 而后将这个 UIView 从它的 superview 中删除掉, 很简单,对吗?

非 Block 的实现方式:

- (void)removeAnimationView:(id)sender
{ [animatingView removeFromSuperview]; }  
- (void)viewDidAppear:(BOOL)animated
{  [super viewDidAppear:animated];
  [UIView beginAnimations:@"Example" context:nil];
  [UIView setAnimationDuration:5.0];
  [UIView setAnimationDidStopSelector:@selector(removeAnimationView)];
  [animatingView setAlpha:0];
  [animatingView setCenter:CGPointMake(animatingView.center.x+50.0,animatingView.center.y+50.0)];
   [UIView commitAnimations];
}

Block 的实现方式:

- (void)viewDidAppear:(BOOL)animated
{ [super viewDidAppear:animated];
  [UIView animateWithDuration:5.0 animations:^{
    [animatingView setAlpha:0];
    [animatingView setCenter:CGPointMake(animatingView.center.x+50.0, animatingView.center.y+50.0)];
} completion:^(BOOL finished) { [animatingView removeFromSuperview]; }];
}

若是咱们仔细看一看这两个方法, 就会发现有 3 个优点:

  1. 更简单的代码 使用 Block, 咱们再也不须要单独定义一个回调方法, 或者调用 beginAnimations/commitAnimations 。
  2. 保持代码在一块儿 使用 Block, 咱们再也不须要在一个地方开启动画,而后再另一个地方处理回调。 全部和咱们动画相关的代码都在一处, 这样让他的可读性和维护性更强。
  3. 苹果推荐这样 这里有一个现实的例子, 苹果已经用 Block 重写了以前的一些功能, 如今苹果官方也推荐,若是可能的话,尽可能迁移到基于 Block 的方法上面。
  4. 何时用 Blocks

    我认为最佳的建议是, 在最合适用 Block 的地方使用它。 这里你可能会出于向后兼容或者更加熟悉之前的方式的缘由,从而还要用老的方法。
    可是每次你面临这种决策的时候, 想想 Block 是否能让你更轻松以及你是否能用基于 Block 的方式代替现有代码。 而后选择一个对你最有价值的方法。

    固然,你可能会发现,在之后的时间里, 你须要愈来愈多的使用 Block, 由于大多数框架,不管是第三方的仍是苹果本身的,都正在用 Block 重写。因此为了让你将来更加轻松,如今就开始使用 Block 吧

相关文章
相关标签/搜索