objective-c —— 代码块
通过代码块(block)功能,你就能像对待对象一般,指定要在方法和函数中传递任意代码部分。
代码块的声明:
int main (int argc, const char * argv[])
{
@autoreleasepool {
void (^myBlock) (NSString *x);//声明变量
/*
代码块是存储在一个变量中,并且需要参数和声明的返回类型。
返回类型:(本类是void)声明代码块的返回值类型的位置所声明变量的类型定义在同一个地方。在代码块声明中声明的值类型就是代码块执行时的返回值类型。
特殊字符^:它告诉编译器所定义的时代码块而不是其他类型的变量。
变量名:(这里时myBlock)存储代码块的变量名,这个变量名使用小括号同其后面的参数隔开。
代码块变量的命名规则和其他变量的命名规则是一样的,必须仅包含数字,字母和下划线,但不能以数字打头。
传入到代码块的参数列表:无需提供参数的变量名,多个参数要用逗号隔开。
分号结束。
*/
myBlock = ^(NSString *x)
{
NSLog(@"%@",x);
};//通过赋值操作利用代码块初始化一个新变量
/*
代码块的定义再次使用^字符,来告诉编译器接下来的内容是代码快的定义。
在定义中可以省略返回值类型,因为编译器可以从存储代码块的变量确定返回值类型。
必须提供代码块的参数说明。
代码块的函数体:位于参数列表的右括号后边,函数体用大括号括起来,可以执行指定的任何操作,在需要时使用参数并在结束后返回适当的值。
*/
}
return 0;
}
前面介绍了代码块的声明和定义,本次将介绍代码块的使用。
在这里分享一个网上链接:http://blog.sina.com.cn/s/blog_71715bf8010166ux.html
1、参数是NSString*的代码块
void (^printBlock)(NSString *x);
printBlock = ^(NSString* str)
{
NSLog(@"print:%@", str);
};
printBlock(@"hello world!");
运行结果是:print:hello world!
2、代码用在字符串数组排序
NSArray *stringArray = [NSArray arrayWithObjects:@"abc 1", @"abc 21", @"abc 12",@"abc 13",@"abc 05",nil];
NSComparator sortBlock = ^(id string1, id string2){
return [string1 compare:string2];
};
NSArray *sortArray = [stringArray sortedArrayUsingComparator:sortBlock];
NSLog(@"sortArray:%@", sortArray);
运行结果:sortArray:( "abc 05", "abc 1", "abc 12", "abc 13", "abc 21" )
3、代码块的递归调用
代码块想要递归调用,代码块变量必须是全局变量或者是静态变量,这样在程序启动的时候代码块变量就初始化了,可以递归调用
static void (^ const blocks)(int) = ^(int i)
{
if (i > 0) {
NSLog(@"num:%d", i);
blocks(i - 1);
}
};
blocks(3);
运行打印结果:
num:3
num:2
num:1
4、在代码块中使用局部变量和全局变量
在代码块中可以使用和改变全局变量
int global = 1000;
int main(int argc, const char * argv[])
{
@autoreleasepool {
void(^block)(void) = ^(void)
{
global++;
NSLog(@"global:%d", global);
};
block();
NSLog(@"global:%d", global);
}
return 0;
}
运行打印结果:
global:1001
global:1001
而局部变量可以使用,但是不能改变。
int local = 500;
void(^block)(void) = ^(void)
{
local++;
NSLog(@"local:%d", local);
};
block();
NSLog(@"local:%d", local);
在代码块中改变局部变量编译不通过。怎么在代码块中改变局部变量呢?在局部变量前面加上关键字:__block
__block int local = 500;
void(^block)(void) = ^(void)
{
local++;
NSLog(@"local:%d", local);
};
block();
NSLog(@"local:%d", local);
运行结果:local:501
以上1,2,3,4部分都为该作者所写,觉得不错就搬过来了,在此再稍微补充几点:
5,代码块为函数形参时的情况
声明一个接受代码块参数的函数
void useCodeBlock(NSComparisonResult (^aBlock) (NSString *value));
使用代码块
void useCodeBlock(NSComparisonResult (^aBlock) (NSString *value))
{
if (NSOrderedSame == aBlock(@"foo"))
NSLog(@"They are the same.");
else
NSLog(@"They are not the same");
}
6,在对象或类方法中使用代码块
-(NSMutableArray *)filterArray:(NSArray *)inArray withBlock:(BOOL (^) (NSInteger))block{
NSMutableArray *result = [NSMutableArray array];
for(NSNumber *number in inArray)
{
if(block([number integerValue]))
[result addObject:number];
}
return result;
}
注意:我们是在代码块定义之后才传入代码块参数的名称(保存代码块的变量在方法体内使用的名称),因此,通常在代码块定义时需要提供代码块变量名的位置却仅传入^符号。(联系代码块的定义)。