Block可以帮助我们组织独立的代码段,并提高复用性和可读性。iOS4在UIKit中引入了该特征。超过100个的Apple API都使用了Block,所以这是一个我们必须开始熟悉的知识。
Block是什么样的?
你可以使用^操作符来声明一个Block变量,它表示一个Block的开始。
int num1 = 7;
int(^aBlock)(int) = ^)int num2) {
return num1+nunm2;
};
在如上代码中我们将Block声明为一个变量,所以可以将它当做一个函数中使用:
NSLog(@"%d", aBlock(49)); //adds 49 to 7 which gives us 56.
我们刚看过了将block当做变量的情况,但通常情况下我们会以内联的方式使用Block,比如在一个变量中。API要么会使用Block在一个对象集合上执行某种操作,要么将其作为一个操作完成后的回调。
NSComperator compareStringsBlock = ^(id stringA, id stringB) {
NSRange rangeS = NSMakeRange (0, [stringA length]);
return (stringA compare:stringB options:comparisonOptions range:rangeS locale:currentLocale];
};
NSArray *compareSortArray = [arrayOfStringDays sortArrayUsingComparator: compareStringsBlock]);
Block具有将临时函数体创建为表达式的优势。Apple文档中指出:
Block是符合如下要求的匿名内联的代码集:
• 和函数一样具有一个指定类型的参数列表
• 有一个可以推导或声明的返回值类型
• 可以从它被定义的词义范围中捕捉状态
• 可以在需要的时候改变词义范围的状态
• 可以和相同的词义范围中定义的其他的Block共享更改的可能。
• 可以在词义范围(堆栈帧)被销毁后继续共享和修改该词义范围(堆栈帧)的状态。
Block是一个自包含的小代码段,封装了用于遍历(线性遍历)或者回调,可以并发执行的任务单元。
声明和使用Block
Apple文档中介绍了如何将一个Block声明为变量,并将其作为一个函数使用:
int (^oneFrom)(int) = ^(int anInt) {
return anInt - 1;
};
// 我们创建了一个内联块^(int anInt)... ,其函数体和结果被传到了另外一个名为OneFrom的Block。
printf("1 from 10 is %d", oneFrom(10));
// 打印出: "1 from 10 is 9"
// 这个block函数(distanceTraveled)传入3个float型参数,返回float值。
float (^distanceTraveled) (float, float, float) =
^(float startingSpeed, float acceleration, float time) {
float distance = (startingSpeed * time) + (0.5 * acceleration * time * time);
return distance;
};
你也可以传入一个Block作为一个参数,而不要以如上的方式声明它们,这样就可以在需要将block作为参数的时候以内联代码的方式简单地实现。
NSArray *anArray = [NSArray arrayWithObjects: @"cat", @"dog",nil];
sortFunction(anArray, ^(string *a string *b){
if ( a == @"cat") return TRUE; });
这样我们就看到一个内联的block代码段占据了最后一个参数(必须是参数列表的最后一个参数)的位置。Cocoa提供了很多使用Block的方法,这样你就可以传入Block作为方法的参数:
NSArray *array = [NSArray arrayWithObjects: @"A", @"B", @"C", nil];
NSSet *filterSet = [NSSet setWithObjects: @"A", @"Z", @"Q", nil];
BOOL (^test)(id obj, NSUInteger idx, BOOL *stop); //Block declaration returns BOOL, params inc. id and BOOL
//body of block gets the block literal ^(id obj, NSUInteger idx, Bool *stop)... and the body logic
test = ^ (id obj, NSUInteger idx, BOOL *stop) {
if (idx < 5) {
if ([filterSet containsObject: obj]) {
return YES;
}
}
return NO;
};
Apple提供的另外一个例子是:
__block BOOL found = NO;
NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma", @"X", nil];
NSString *string = @"gamma";
//we provide below a way of how to enumerate, using our own compare logic
[aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) {
*stop = YES;
found = YES;
}
}];
掌握它需要一点时间,但一旦领会了还是很简答的,是不?我建议大家看下Apple的文档,并看看其中引用到的一些API以确认下它们是如何使用的。多练习,熟能生巧!
分享到:
相关推荐
如何在iOS中使用Block──How to use Blocks with iOS
iOS block使用总结 可以结合博客http://blog.csdn.net/aiyang10/article/details/49328969理解
iOS的block是学习的难点和重点,熟练使用block可以达到代码的简单高效,特别是在网络的使用过程中。Block demo是一个简单易学的,可以便于学习原理。
该文档简单的介绍了ios下block是的使用方法和一些小技巧
把block当成属性放在单例字典中,可以帮你跨界面,在任意一个地方都可以访问到这个block,之所以上传,是因为看到很多人还在使用代理传值,觉得费时间,这个demo简单易懂,真的好用
iOS Block 的使用, 包括传值, 基本用法
iOS Block 的 基本使用 演示 在Controller之间传值 和 传点击相应事件
UIButton类在使用时需要一行行的来设置属性,代码过于冗余。每个点击事件都要创建一个方法,不利于阅读。最新代码地址:https://github.com/Maricle1/ControlsPackage.git
iphone开发中block的详解.pages
IOS block回调代码实例Demo IOS block 回调 Demo 块
源码github.com/pro648/BasicDemos-iOS/tree/master/Block 块是一个独立的代码片段,始终存在于另一个编程结构的范围内,如在一个方法的主体。块可以捕获块外变量的值,但外部对于块内发生的事情一无所知。...
iOS 常用block 传值
用代码块实现两个不同视图直接的传值问题,用代码块实现起来比协议更方面。
方法来触发按钮的动作,而改成用一个block的方式来出发动作,这样处理后,一可以降低代码的分散度,二当我再次查看按钮的触发方法实现细节时就不用点command跳到方法里,而是在按钮的初始化位置就能看到按钮的点击...
iOS底层原理进阶,从底层原理和本质详细解析block的使用
翻译的Pro Multithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks中的block章节
iOS学习——block深入浅出博文中的代码 博文地址:http://blog.csdn.net/u010127917/article/details/49946527
一个block回调的例子
已经拥有一年经验的你真的了解Block 代理方法吗?也许不!以前我以为自己都有上架项目,这都是太基础的东西,但今天我重新回头看了以前做的笔记,真的是书读百遍,其义自见。
block的使用 简单易懂 1 block作为局部变量 2 block作为属性 全局 3 block作为函数的参数