开始: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. Dhaka2011

    Dhaka2011 A - Binary Matrix 题目描述:有一个\(n \times m\)的\(01\)矩阵,这一矩阵第一行和最后一行是相邻的,第一列和最后一列是相邻的,现在每次可以交换相邻 ...

  2. InteliJ IDEA 简单使用:配置项目所需jdk

    1:配置项目所需jdk: File->Project Structure 弹出如下界面: 首先选中SDKs,会出现下图界面:点击“+”标志弹出Add New SDK 然后选择JDK,会弹出路径框 ...

  3. 谈谈如何查看Android项目方法数

    我们都知道,Android App的方法数是有天花板的,在方法数达到65536时,就会出现打包异常,这个时候,我们需要去除一些不需要的三方工具包,或者采用多Dex技术分包,都能达到正常打包的效果. 可 ...

  4. MySQL 5.6表空间传输

    在MySQL 5.6 Oracle引入了一个可移动表空间的特征(复制的表空间到另一个服务器)和Percona Server采用部分备份,这意味着你现在可以备份单个数据库或表:由于Percona Ser ...

  5. 第二届CCF软件能力认证

    1. 相邻数对 问题描述 给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1. 输入格式 输入的第一行包含一个整数n,表示给定整数的个数. 第二行包含所给定的n个整数. 输出格式 输出一个 ...

  6. k8s的imagePullSecrets如何生成及使用

    如果公司的docker仓库(harbor),需要用户认证之后,才能拉取镜像. 那如何在k8s里生成这个secret呢? 这个secret如何还原呢? 在k8s的yaml文件里如何实现呢? 这里提供几个 ...

  7. 发送统计邮件shell脚本

    #!/bin/bash#作者:Presley#时间:2018.07.16#监控阿里云aaa库的py_weixin_product_close_rating_info 和 py_weixin_produ ...

  8. C语言结构体在内存中的存储情况探究------内存对齐

    条件(先看一下各个基本类型都占几个字节): void size_(){ printf("char类型:%d\n", sizeof(char)); printf("int类 ...

  9. 013.Zabbix的Items(监控项)

    一 Items简介 Items是从主机里面获取的所有数据,可以配置获取监控数据的方式.取值的数据类型.获取数值的间隔.历史数据保存时间.趋势数据保存时间.监控key的分组等. 通常情况下item由ke ...

  10. css细节:尖角处理

    在各种网站里面,我们会经常看到类似于这样的尖角:(示例:新浪微博) 它实现的方式有多种,哪种才是最简单的?哪种才是最优秀的?首先我声明一下,我还不清楚这个东西具体叫什么名字(哪位知道还望告知),暂且叫 ...