文章来源:blog.csdn.net/totogo2010/…
代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。
脱字符(^)是块的语法标记。按照我们熟悉的参数语法规约所定义的返回值以及块的主体(也就是可以执行的代码)。下图是如何把块变量赋值给一个变量的语法讲解:\
\
按照调用函数的方式调用块对象变量就可以了:
int result = myBlock(4); // result是 28\
1、参数是NSString*的代码块
[cpp] view plain copy
- void (^printBlock)(NSString *x);
- printBlock = ^(NSString* str)
- {
- NSLog(@"print:%@", str);
- };
- printBlock(@"hello world!");
运行结果是: print:hello world!
2、代码用在字符串数组排序
[cpp] view plain copy
- 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、代码块的递归调用
代码块想要递归调用,代码块变量必须是全局变量或者是静态变量,这样在程序启动的时候代码块变量就初始化了,可以递归调用
[cpp] view plain copy
- 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、在代码块中使用局部变量和全局变量
在代码块中可以使用和改变全局变量
[cpp] view plain copy
- 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
而局部变量可以使用,但是不能改变。
[cpp] view plain copy
- int local = 500;
- void(^block)(void) = ^(void)
- {
- local++;
- NSLog(@"local:%d", local);
- };
- block();
- NSLog(@"local:%d", local);
在代码块中改变局部变量编译不通过。怎么在代码块中改变局部变量呢?在局部变量前面加上关键字:__block
[cpp] view plain copy
- __block int local = 500;
- void(^block)(void) = ^(void)
- {
- local++;
- NSLog(@"local:%d", local);
- };
- block();
- NSLog(@"local:%d", local);
运行结果: local:501
local:501
著作权声明:本文由blog.csdn.net/totogo2010/原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!
\
学习block之前先用弄懂c语言的函数指针
看代码:
typedef int (^SumP)(int,int);//用typedef定义一个block类型
\
void test()
{
printf("调用了test函数\n");
}
\
int sum(int a,int b)
{
return a+b;
}
int main(int argc,constchar * argv[])
{
void (*p)();//这是一个函数指针 能够指向一个返回值为void 没有形参的函数\
//(*p)是固定写法,代表指针变量p将来肯定指向函数
//左边的void:指针变量p指向的函数没有返回值
//右边():指针变量p指向的函数没有形参
p = test;//指针变量p指向test函数
//利用指针变量间接调用取出函数
(*p)();
//也可以
p();
int(*xp)(int,int);//定义一个指向函数的指针返回值是int 函数的参数是int int
xp =sum;
int c = (*xp)(1,2);
printf("c is %d\n",c);
\
//下面来学习block
/*
作用:
Block封装了一段代码,可以在任何时候执行
Block可以作为函数参数或者函数的返回值,而本身又可以带输入参数或返回值
block,在多线程、异步任务,集合遍历,集合排序、动画专场用得多
*/
//block用来保存一段代码
//block的标志 :^
//block跟函数指针很像
//定义block变量没有返回值没有参数
void(^myblock)() = ^ {
NSLog(@"---------");
NSLog(@"---------");
};
//利用block变量调用block内部的代码
myblock(); //运行block
//定以一个block返回值为int函数的参数为int int
int(^sumblock)(int ,int ) = ^(int a,int b){
return a + b;
};
int sum = sumblock(10,11);
NSLog(@"sum = %d",sum);
\
//利用typedef定义block来创建一个block变量
SumP sumblock1 = ^(int a,int b){
return a - b;
};
int d = sumblock1(10,5);
NSLog(@"d = %d",d);
\
return 0;
}
\
作为方法或函数参数时,块可用作回调。被调用时,方法或函数执行部分工作,并在适当时刻,通过块回调正在调用的代码,以从中请求附加信息,或获取程序特定行为。块使调用方在调用时能够提供回调代码。块从相同的词法作用范围内采集数据(就像宿主方法或函数所做的那样),而非将所需数据打包在“关联”结构中。由于块代码无需在单独的方法或函数中实现,您的实施代码会更简单且更容易理解。
Objective-C 框架具有许多含块参数的方法。例如,Foundation 框架的 NSNotificationCenter 类声明以下方法,该方法具有一个块参数:
| ```
- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block
| -------------------------------------------------------------------------------------------------------------------------------------------------- |
此方法将一个观察者添加到通知中心(通知在**采用设计模式使您的应用程序合理化**中有介绍)。指定名称的一则通知发布时,块被调用以处理该通知。
| ```
opQ = [[NSOperationQueue alloc] init];
``` |
| ------------------------------------------------------------------------------------------------- |
| ```
[[NSNotificationCenter defaultCenter] addObserverForName:@"CustomOperationCompleted"
``` |
| ```
object:nil queue:opQ
``` |
| ```
usingBlock:^(NSNotification *notif) {
``` |
| ```
// handle the notification
``` |
| ```
}];
``` |
\