开始:Block 简介

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

即使有这么多好处, 还是有很多开发者没有使用 Block, 因为他们不知道如何使用。 但是 Block 绝对是你作为一个 Objective-C 程序员,一定会想要掌握的技能。

让我们来看看 Block 是谁, 是什么,在哪里用它, 为什么用它, 还有什么时候用它。

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

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 的方法上面。 (来源)

什么时候用 Blocks

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

当然,你可能会发现,在以后的时间里, 你需要越来越多的使用 Block, 因为大多数框架,无论是第三方的还是苹果自己的,都正在用 Block 重写。所以为了让你未来更加轻松,现在就开始使用 Block 吧。

参考:http://www.raywenderlich.com/zh-hans/18753/如何在-ios-5-中使用-block-2

理解 block的更多相关文章

  1. 对于block的理解,block的面试题

    1.block跟swift中的闭包(closure)基本一样,都常用于值的回调,特别是在多线程的网络请求回调中,使用起来极为方便. 2.block的开头是"^",接着是由小括号所报 ...

  2. 深入理解block

    2010年WWDC发布iOS4时Apple对Objective-C进行了一次重要的升级:支持Block.说到底这东西就是闭包,其他高级语音例如Java和C++已有支持,第一次使用Block感觉满简单好 ...

  3. 理解block和inode

    什么是block和inode? 定义:block就像是杯子 inode就像是杯子的编号,因为杯子太多了 1.根据文件的大小,在磁盘中储存时会占用一个或多个block:那么究竟多大的文件会使用一个blo ...

  4. 从汇编代码理解 Block 的内存结构

    ❓ 在断点调试 iOS 程序碰到 block 作为函数的形参时,如果想知道该 block 本身的函数签名信息和函数体地址时,有哪些办法?

  5. Block使用

    1.对block的理解 >  block是iOS4.0之后出现的,是仿照java中匿名函数所创造的,它是c级别的语法,效率比协议-代理高 >  block的是一个匿名函数(没有名字的函数) ...

  6. 理解 Cinder 架构 - 每天5分钟玩转 OpenStack(45)

    从本节开始我们学习 OpenStack 的 Block Storage Service,Cinder 理解 Block Storage 操作系统获得存储空间的方式一般有两种: 通过某种协议(SAS,S ...

  7. Block、委托、回调函数原理剖析(在Object C语境)——这样讲还不懂,根本不可能!

    开篇:要想理解Block和委托,最快的方法是搞明白“回调函数”这个概念. 做为初级选手,我们把Block.委托.回调函数,视为同一原理的三种不同名称.也就是说,现在,我们把这三个名词当成一回事.在这篇 ...

  8. Block介绍(二)内存管理与其他特性

    我们在前一章介绍了block的用法,而正确使用block必须要求正确理解block的内存管理问题.这一章,我们只陈述结果而不追寻原因,我们将在下一章深入其原因. 一.block放在哪里 我们针对不同情 ...

  9. Magento Block设计分析(深入分析)

    Magento中Block是一个很重要的组件,它在Block中充当非常重要的角色,下面我们来分析一下Magento中Block是怎样设计的,我们应该怎样使用这个重要的角色. 1.Magento Blo ...

随机推荐

  1. plsql 查询 卡死问题解决

    plsql可以连接数据库,一点查询就卡死.sqlplus可以连接数据库,也可以查询.后经过测试,原来plsql所引用的路由器ip和服务器ip有限制,修改同一网段ip问题解决.但是不知为何不同网段ip可 ...

  2. 解除IIS配置节锁定

    C:\windows\system32\inetsrv\appcmd unlock config -section:system.webServer/modules

  3. Java与PHPweb开发比较

    参考:https://blog.csdn.net/loophome/article/details/83413878

  4. Python_oldboy_自动化运维之路_面向对象(十)

    面向对象编程 OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向 ...

  5. 2011TG初赛

    一.单项选择题(共20题,每题1.5分,共计30分,每题有且仅有一个正确选项.) 1. 在二进制下,1011001+( )=1100110. A.1011 B.1101 C.1010 D.1111 B ...

  6. ERP渠道文档管理(二十四)

    基本需求: 用例图: 存储过程: CREATE PROCEDURE [dbo].[BioErpCrmChannelDocument_ADD] @DocumentID int, @ChannelID i ...

  7. Error:The supplied javaHome seems to be invalid. I cannot find the java executable. Tried location:

    在Android studio 或者intellij idea中新创建一个项目或者打开一个存在的项目时,有时候会出现Error:The supplied javaHome seems to be in ...

  8. Qt编程之悲惨世界

    最近需要给人写点基于QtWebkit的代码,算是领教了Qt编程的痛苦之处. QNetworkConfigurationManager::isOnline() 只有在编译平台上能运行,拷贝到其他Wind ...

  9. 领英Linkedin信息搜集工具InSpy

    领英Linkedin信息搜集工具InSpy   领英Linkedin是一个知名职业社交媒体网站.通过该网站,渗透测试人员可以获取公司内部组成和员工信息.Kali Linux提供一款专用的信息收集工具I ...

  10. ubuntu VNC中Xfce4中Tab键失效的解决方法

    转:https://blog.csdn.net/xuezhisdc/article/details/48662435 说明 在Ubuntu Server 14.04上安装了xfce4桌面环境,但是却发 ...