`

在iOS4中使用代码块-基础知识

    博客分类:
  • ios
阅读更多

翻译自 http://pragmaticstudio.com/blog/2010/7/28/ios4-blocks-1
译者水平有限,建议阅读原帖

    iOS4引入了一个新特性,支持代码块的使用,这将从根本上改变你的编程方式。代码块是对C语言的一个扩展,因此在Objective-C中完全支持。如果你学过Ruby,Python或Lisp编程语言,那么你肯定知道代码块的强大之处。简单的说,你可以通过代码块封装一组代码语句并将其当作一个对象。代码块的使用是一种新的编码风格,可以让你运用自如的使用iOS4中新增API。
    我们先来看两个在iOS4中使用代码块的例子(你很有可能已经见过):view animations 和enumeration
使用代码块的例子
     第一个例子,假设我们创建一个纸牌游戏,需要展现纸牌被派发到玩家面前的动画效果。幸运的是通过UIKit框架可以很容易的实现一个动画效果。但是最终是什么样的动画是由你的程序决定的。你可以在代码块中指定动画的内容然后再将代码块传给animateWithDuration:animations:方法,像下面这样:
[UIView animateWithDuration:2.0
    animations:^ {
        self.cardView.alpha = 1.0;
        self.cardView.frame = CGRectMake(176.0, 258.0, 72.0, 96.0);
        self.cardView.transform = CGAffineTransformMakeRotation(M_PI);
    }
];

    当这个动画代码块执行时,我们的纸牌会展现三种方式的动画:改变它的alpha值从而淡入显示,改变它的位置到右下角(玩家的位置),以及自转180度(为了使其效果更好)。
第二个代码块的例子是迭代一个纸牌的集合,并打印其名字和在集合里的索引值。
你可以通过使用for循环来达到目的,但是在iOS4中NSArray类有一个使用了代码块的方便方法:enumerateObjectsUsingBlock:。下面是如何使用它:

NSArray *cards = [NSArray arrayWithObjects:@"Jack", @"Queen", @"King", @"Ace", nil];
 
[cards enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
    NSLog(@"%@ card at index %d", object, index);
}];

    这个代码块使用了三个参数:数组中的一个对象,该对象的索引,以及一个标识迭代是否结束的标志。我们稍候再对其进一步探讨。enumerateObjectsUsingBlock: 这个方法会将集合中的每一个元素传入相应的参数并调用代码块中的方法。
    因此在你的mac和iOS程序中使用代码块的优势是:它允许你附加任意的代码到苹果官方提供的方法上。尽管在概念上与代理相似,但是在方法中使用简短的内联代码块往往更加方便,更加优雅。
    这是一个好的开始,但重要的是要明白它内部的处理。当我学习新东西的时候,我喜欢先将其分为一个个简单的部分,了解它们如何工作,然后再将它们组装到一块,这样我会对自己写的代码以及快速解决出现的问题充满信心。因此,让我们先回头学习下如何声明和调用简单的代码块。
代码块的基本概念
    一个代码块可以简单看作是一组可执行的代码。例如,下面是一个打印当前日期和时间的代码块:
^ {
    NSDate *date = [NSDate date];
    NSLog(@"The date and time is %@", date);
};
    插入符号(^)声明一个代码块的开始,一对大括号{}构成了代码块的体部。你可以认为代码块与一个匿名函数类似。那么,如果是一个匿名的函数,我们该怎么调用这个代码块呢?最常见使用代码块的方式是将其传入方法中供方法回调,就像之前我们已经见到了view animations 和enumeration。另一种使用代码块的方式是将其赋予代码块变量,然后可使用该变量来直接调用代码块。以下是如何声明我们的代码块并将它赋予代码块变量now:
void (^now)(void) = ^ {
    NSDate *date = [NSDate date];
    NSLog(@"The date and time is %@", date);
};
    声明一个块变量的语法需要一些时间适应,这才有趣。如果你使用过函数指针,代码块变量与其类似。在上面代码等号右边是我们已经介绍过的代码块。等号左边我们声明了一个代码块变量now。

 
    代码块变量之前有^符号并被小括号包着,代码块变量有类型定义的。因此,上图中的now变量可以应用任何无参,无返回值的代码块。我们之前声明的代码块符合这要求,,所以我们可以放心的把它分配给now变量。
    只要有一个代码块变量,并在其作用域范围内,我们就可以像调用函数一样来调用它。下面是如何调用我们的代码块:
now();
    你可以在C函数或者Objective-c方法中声明代码块变量,然后在同一作用域内调用它,就像我们前面说明那样。当代码块执行时,它打印当前的日期和时间。目前为止,进展顺利。
代码块是闭包
    如果这就是代码块的全部的话,那么他与函数是完全相同的。但事实是代码块不仅仅是一组可执行的代码。代码块能够捕捉到已声明的同一作用域内的变量,同时由于代码块是闭包,在代码块声明时就将使用的变量包含到了代码块范围内。为了说明这一点,让我们改变一下前面的例子,将日期的初始化移到代码块之外。
NSDate *date = [NSDate date];
 
void (^now)(void) = ^ {
    NSLog(@"The date and time is %@", date);
};
 
now();
    当你第一次调用这个代码块的时候,它与我们之前的版本结果完全一致:打印当前的日期和时间。但是当我们改变日期后再调用代码块,那么就会有显著的不同了,
sleep(5);
 
date = [NSDate date];
  
now();
    尽管我们在调用代码块之前改变了日期,但是当代码块调用时仍然打印的是之前的日期和时间。就像是日期在代码块声明时停顿了一样。为什么会这样呢,当程序执行到代码块的声明时,代码块对同一作用域并且块内用到的变量做一个只读的备份。你可以认为变量在代码块内被冻结了。因此,不论何时当代码块被调用时,立即调用或5秒钟之后,只要在程序退出之前,它都是打印最初的日期和时间。
    事实上,上面那个展示代码块是闭包的例子并不十分完善,毕竟,你可以将日期作为一个参数传入到代码块中(下面讲解)。但是当你将代码块在不同方法间传递时闭包的特性就会变得十分有用,因为它里面的变量是保持不变的。
代码块参数
    就像函数一样,代码块可以传入参数和返回结果。例如,我们想要一个能够返回指定数的三倍的代码块,下面是实现的代码块:
^(int number) {
    return number * 3;
};
    为代码块声明一个变量triple,如下:
int (^triple)(int) = ^(int number) {
    return number * 3;
};
    上面说过,我们需要熟悉等号左边声明代码块变量的语法。现在让我们从左到右分开来说明:

 
最左边的int是返回值类型,中间是小括号包围插入符号^及代码块变量的名字,最后又一个小括号,包围着参数的类型(上面例子中只有一个int参数)。等号右边的代码块声明必须符合左侧的定义。有一点要说明的是,为了方便,可以不声明代码块的返回类型,编译器会从返回语句中做出判断。
    要调用这个代码块,你需要传入一个需要乘3的参数,并接受返回值,像这样:
int result = triple(2);

    下面你将知道如何声明并创建一个需要两个int型参数,将它们相乘然后返回结果的代码块:
int (^multiply)(int, int) = ^(int x, int y) {
    return x * y;
};

    这是如何调用这个代码块:
int result = multiply(2, 3);

    声明代码块变量使我们有机会探讨代码块类型以及如何调用。代码块变量类似函数指针,调用代码块与调用函数相似。不同于函数指针的是,代码块实际上是Objective-C对象,这意味着我们可以像对象一样传递它们。
调用代码块的方法
    在实际中,代码块经常被作为参数传入方法中供其回调。当把代码块作为一个参数时,相比分配一个代码块变量,更通常的做法是作为内联代码块。例如,我们之前看到的例子:view animations 和enumeration。
    苹果官方已经增加了一些使用代码块的方法到他们的框架中。你也可以写一些使用代码块的API了。例如,我们要创建一个Worker类的使用代码块的类方法,该方法重复调用代码块指定的次数,并处理代码块每次返回的结果。下面是我们使用内联代码块调用这个方法,代码块负责返回1到10的每个数的三倍。
[Worker repeat:10 withBlock:^(int number) {
    return number * 3;
}];

    这个方法可以将任何接受一个int型参数并返回一个int型结果的代码块作为参数,如果想得到数字的二倍,只需要改变传入方法的代码块。
到你动手的时候了
    那么你将如何去实现上面我们使用的 repeat:withBlock:这个方法,考虑一下,我们将在下期给出分解。在此期间,通过调用enumerateKeysAndObjectsUsingBlock: 方法打印一个NSDictiobary的键和值来练习使用代码块:
NSDictionary *cards = 
    [NSDictionary dictionaryWithObjectsAndKeys:@"Queen",  @"card", 
                                               @"Hearts", @"suit", 
                                               @"10",     @"value", nil];

分享到:
评论

相关推荐

    OBJECTIVE-C编程之道 IOS设计模式解析电子书+源代码

    C协议实现适配器模式8.5 用Objective-C的块在iOS 4中实现适配器模式8.5.1 块引用的声明8.5.2 块的创建8.5.3 把块用作适配器8.6 总结第9章 桥接9.1 何为桥接模式9.2 何时使用桥接模式9.3 创建iOS版虚拟仿真器9.4 总结...

    Objective-C基础教程(第2版)

    本书三位作者是顶级苹果专家,书中以苹果最新的Xcode 4.x工具为基础,详细讲述了Objective–C的全部基础知识,涵盖了块、GCD、ARC、类扩展、继承、组合、对象初始化、分类、协议、内存管理和组织源文件等新主题,...

    ios-Block基础,block传值,及自定义block方法.zip

    block基础知识及block应用。 本例介绍了使用block实现界面传值,自定义带有block代码块的方法。

    【全新正版】现代C++程序设计(原书第2版)

    3.2.2 问题分析:在if语句中使用大括号 3.2.3 if-else if-else语句 3.2.4 低效的编程方法 3.2.5 if-else程序示例 3.2.6 嵌套if-else语句 3.2.7 条件运算符“?” 3.3 switch语句 3.4 循环 3.4.1 括号的用法 3.4.2 ...

    毕设&课设&项目&实训-涉及到scrapy多块知识,同时涉及几项应对反爬虫设计,最后使用sqlalchemy将爬得结.zip

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同...

    基于C语言实现别踩白块儿(双人版)源码(含源代码+使用说明).rar

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步...

    仿九块邮触屏版淘宝客单页手机wap购物网站模板_网站开发模板含源代码(css+html+js+图样).zip

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步...

    什么是VLAN

     局域网的发展是VLAN产生的基础,所以在介绍VLAN之前,我们先来了解一下局域网的有关知识。  局域网(LAN)通常是一个单独的广播域,主要由Hub、网桥或交换机等网络设备连接同一网段内的所有节点形成。处于同一个...

    仿写的类似支付宝二维码扫描

    本demo是仿写的支付宝的大体效果,部分代码借鉴高少东的,并且在他的基础上添加了很多补充功能,并对他的代码做了一些优化。 本demo是我最近在整理的oc教程篇中的其中一篇,以后还会陆续出一些oc上的教程,有的侧重...

    Linux kernel pdf 每一行都完全注释-初学者必备

    阅读本书需具备的基础知识 3 使用早期版本是否过时? 3 EXT2 文件系统与MINIX 文件系统? 4 第1 章 概述 5 11 LINUX 的诞生和发展 5 12 内容综述 9 13 本章小结 12 第2 章 LINUX 内核体系结构 13 21 LINUX 内核模式 ...

    OpenGL ES 3.0

    这些着色语言基础知识包括变量和类型、构造器、结构、数组、统一变量、统一变量块(uniform block)和输入/输出变量。该章还描述着色语言的某些更细微的部分,例如精度限定符和不变性。  第6章——顶点属性、顶点...

    c语言别踩白块儿(双人版)源码.rar

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步...

    基于HTML实现的仿九块邮触屏版淘宝客单页手机wap购物网站模板(css+html+js+图样).zip

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步...

Global site tag (gtag.js) - Google Analytics