ios 添加block 类别_iOS objective-c之-3:类别Block对象

block 对象的使用是在iOS4以后才支持的特色,严格的来说,block对象属于c语言的特色,因此其调用也和c语言一样,那么为什么ISO会需要block呢?这是因为在iOS应用程序内大量使用target-action的机制,所以可能需要在痛一个类里面编写很多的回调函数。对于某些只使用一次的函数来说,这显然不具有经济效益。

那么介绍一下block:

一、什么是Blocks Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block。 二、在ios开发中,什么情况下使用Block Block除了能够定义参数列表、返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态。此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围(比如栈展开,出了作用域),仍可以继续共享或者修改这些状态。通常来说,block都是一些简短代码片段的封装,适用作工作单元,通常用来做并发任务、遍历、以及回调。 三、block如何申明(对比于c语言中的函数申明)

四、c函数指正和blocks调用 int (*CFunc) (int a) 函数调用 int result = CFunc(10); int (^BFunc)  (int  a)  函数调用 int result = BFunc(10); 五、__block  关键字 一个Block的内部时可以引用自身作用域外的变量的,包括static变量,extern变量或自由变量(定义一个变量的时候,如果不加存储修饰符,默认情况下就是自由变量auto,auto变量保存在stack中的。除了auto之外还存在register,static等存储修饰符),对于自由变量,在Block中只读的。在引入block的同时,还引入了一种特殊的__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;

}

}];

As you can see, it takes a little while to have it sink in but once you get it, it's quite simple. I suggest looking at Apple's documentation, as well as looking at the referenced APIs to see how they are used. Practice makes perfect.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值