`

在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];

分享到:
评论

相关推荐

    ios应用源码之感恩---奉上大量samplecode(第一部分) samplecode1 2018128

    首先,"源码"在iOS开发中通常指的是Objective-C或Swift编写的代码,它们构成了应用程序的基础。开发者通过阅读和分析源码,可以学习到如何使用Apple的UIKit框架创建用户界面,如何处理事件,以及如何与其他系统服务...

    IOS-解压-压缩-ZIP-ZLibDemo

    在iOS开发中,处理文件的压缩和解压是常见的需求,特别是在数据传输或者备份场景下。...总之,理解ZLib和ZIP文件格式的基础知识,以及如何在iOS中有效地使用它们,对于任何iOS开发者来说都是非常有价值的。

    iOS游戏应用源代码——buckybush-Blackjack-f4cd417.zip

    6. **内存管理**:iOS使用ARC(Automatic Reference Counting)进行内存管理,学习如何在代码中正确使用强引用、弱引用以及何时释放对象,可以避免内存泄漏问题。 7. **数据持久化**:如果项目包含保存游戏进度的...

    iOS游戏应用源代码——vicpenap-VPPDropDown-0.3.0-0-g3f3e9e4.zip

    为了实现下拉菜单的动态显示和隐藏,开发者可能使用Core Animation框架,或者直接在UIView的动画块中进行配置。这些动画可能涉及到视图的透明度、位置和大小变化。 8. **响应式编程( Reactive Programming)** ...

    iOS游戏应用源代码——joshvera-iPhone-Tetris-2dd7365.zip

    通过分析源代码,我们可以了解如何在iOS平台上构建一款游戏,包括图形渲染、游戏逻辑、音效处理、用户交互以及版本控制等方面的知识。对于初学者来说,这是一个很好的实践平台,而对于有经验的开发者,它可以作为...

    iOS游戏应用源代码——hsjunnesson-UIViewDrawRectBlock-09ba68a.zip

    通过研究这个项目,开发者不仅能学习到iOS应用开发的基础知识,还能深入理解`UIView`的绘图机制,掌握块的高级用法,并对性能优化有更深刻的认识。这将有助于提升开发者在实际项目中的问题解决能力,打造更加高效、...

    iOS游戏应用源代码——rieyamane-Janken-beb858e.zip

    在iOS开发领域,源代码分析是提升技术能力、学习新知识的重要途径。本篇将深入探讨名为"rieyamane-Janken-beb858e"的iOS游戏应用源代码,该应用基于Objective-C或Swift语言编写,旨在实现经典的“剪刀石头布”...

    iOS纯代码画圆形图

    在iOS开发中,有时我们需要自定义视图来呈现特定的数据或设计效果,比如画出圆形图。本示例提供了一个简单的iOS应用,它使用Objective-C(OC)语言实现了纯代码绘制圆形图的功能,而且带有半封装的形式,方便开发者...

    iOS实例开发源码——drewish-munchem-8f7f405.zip

    在深入探讨这个项目之前,我们需要先了解iOS开发的基础知识。 iOS开发主要依赖于Apple的Xcode集成开发环境(IDE),它包含了编写、测试和调试iOS应用所需的所有工具。Xcode支持Swift和Objective-C两种编程语言。Swift...

    Ios学习代码:OC课程代码

    "Ios学习代码: OC课程代码"这个资源集合了作者在学习Objective-C过程中编写的示例代码,涵盖了OC的基础概念、语法特性以及与iOS开发相关的实践应用。 1. **Objective-C简介** Objective-C是在C语言基础上扩展的一...

    iOS游戏应用源代码——atomton-ATMHud-fc79fed.zip

    在这个源代码中,我们可以期待看到如何使用UIView、UIViewController等基本UI元素,以及可能用到的UILabel、UIButton、UIProgressView等控件来构建Hud界面。此外,可能会涉及到动画效果,如UIView动画或者Core ...

    iOS动画够用了,Animation-explore-可运行

    UIView的`animateWithDuration:animations:`方法提供了一种简洁的方式创建动画,它接受一个代码块作为参数,该代码块定义了动画期间发生的改变。此外,还有更高级的`animate(withDuration:delay:options:animations:...

    iOS游戏应用源代码——LemonCake-OmNomDonuts-CoreAnimation.zip

    1. 层(Layer)与视图(View)的关系:在iOS中,UIView对象是用户界面的基本构建块,而CALayer则处理视图的渲染。每个UIView都有一个关联的CALayer,开发者可以通过操作Layer来改变View的显示效果。 2. 属性动画:...

    iOS游戏应用源代码——ionine-Sauce-86a98eb.zip

    3. **SpriteKit框架**:鉴于这是一个游戏应用,我们很可能在源代码中看到SpriteKit的使用。SpriteKit是一个2D游戏引擎,支持动画、物理模拟、粒子效果等功能,适合开发轻量级游戏。 4. **GameplayKit**:如果游戏...

    iOS实例开发源码——fcarucci-Diamonds-d0eaa94.zip

    在iOS开发中,游戏往往涉及到Cocoa Touch框架,该框架提供了用户界面的构建块,如UIView和UIViewController,它们是实现游戏界面的基础。 在项目中,我们可能会发现使用了SpriteKit或SceneKit这样的游戏引擎。...

    iOS游戏应用源代码——r3econ-UIImage-Sprite-Additions-0738b37.zip

    在iOS游戏开发中,源代码是开发者理解和控制应用程序运行的核心部分。这个名为“r3econ-UIImage-Sprite-Additions-0738b37.zip”的压缩包包含了一个针对iOS平台的游戏应用的源码,特别关注了UIImage类的扩展,以支持...

    IOS应用源码——Objective-C基础教程 随书源码.zip

    通过分析并实践“Learn Objective-C Samples”中的示例代码,你可以逐步掌握Objective-C的基础知识,并为进一步学习iOS应用开发打下坚实基础。每个示例都是一个独立的知识点,逐一研究并运行它们,将有助于深化理解...

    IOS应用源码Demo-电子书阅读器 - iOS PDF Reader-毕设学习.zip

    【标题】"IOS应用源码Demo-电子书阅读器 - iOS PDF Reader-毕设学习.zip" 是一个专门针对iOS平台的电子书阅读器应用程序的源代码...尽管技术在不断更新,但基础知识和编程原理依然适用,因此这个项目仍然值得深入研究。

    iOS程序开发教程(PPT+代码)

    在本“iOS程序开发教程”中,我们涵盖了多个关键知识点,包括iOS应用的基本架构、编程语言、用户界面设计以及数据存储。以下是对每个讲座主题的详细解析: 1. **MVC(模型-视图-控制器)模式**:Title Lecture 1 ...

    IOS5开发经典基础实例20例

    《iOS5开发经典基础实例20例》是针对苹果iOS平台开发者的一份...每个实例都是一个独立的主题,涵盖了iOS开发的各个方面,让学习者在实践中不断提升自己的技能。无论是对新手还是有一定经验的开发者,都能从中受益匪浅。

Global site tag (gtag.js) - Google Analytics