黑马程序员技术交流社区
标题:
block问题?
[打印本页]
作者:
陈志辉
时间:
2014-4-2 09:26
标题:
block问题?
本帖最后由 陈志辉 于 2014-4-2 11:28 编辑
block怎么使用的?
作者:
Lin枫
时间:
2014-4-2 09:44
宣告和使用Block
我们使用「^」运算子来宣告一个block变数,而且在block的定义最后面要加上「;」来表示一个完整的述句(也就是将整个block定义视为前面章节所介绍的简单述句,因为整个定义必须是一个完整的句子,所以必须在最后面加上分号),下面是一个block的范例:
1: int multiplier = 7 ;
2: int (^myBlock)( int ) = ^( int num)
3: {
4: return num * multiplier;
5: };
我们宣告一个「myBlock」变数,用「^」符号来表示这是一个block。
这是block的完整定义,这个定义将会指定给「myBlock」变数。
表示「myBlock」是一个回传值为整数(int)的block。
它有一个参数,型态也是整数。
这个参数的名字叫做「num」。
这是block的内容。
值得注意的地方是block可以使用和本身定义范围相同的变数,可以想像在上面的例子中 multiplier 和 myBlock 都是某一个函数内定义的两个变数也就是这个变数都在某个函数两个大括号「{」和「 }」中间的区块,因为它们的有效范围是相同的,因此在block中就可以直接使用 multiplier 这个变数,此外当把block定义成一个变数的时,我们可以直接像使用一般函数般的方式使用它:
1: int multiplier = 7 ;
2: int (^myBlock)( int ) = ^( int num)
3: {
4: return num * multiplier;
5: };
6: printf ( "%d" , myBlock( 3 ));
7: //结果会打印出21
作者:
陈志辉
时间:
2014-4-2 11:28
Lin枫 发表于 2014-4-2 09:44
宣告和使用Block
我们使用「^」运算子来宣告一个block变数,而且在block的定义最后面要加上「;」来表示一 ...
谢谢啦哈
作者:
agelessman
时间:
2014-4-2 11:30
语法
1,block的声明格式:
返回值类型(^block的名字)(参数类型1,参数类型2,.......)
2,block的定义格式:
^返回值类型(参数类型1 参数名,参数类型2 参数名.......){return 返回值类型;}
如:void(^myBlock)(int a);
typedef void(^blockType)(int a);//声明block类型为blockType
blockType myblock;//声明blcok变量 myblock
myblock = ^(int a){return a*a};//变量myblock赋值
myblock(2);//block调用
注:返回值类型是可以省略的
如:int (^add) (int,int) = ^(int number1,int number2){return number1+number2;}
typedef void (^blockType)(void)
- (void)method:(id)obj block:(blockType)block 或者
- (void)method:(id)obj block:(void(^)(void))block (参考UIView animation block)
[ obj method:obj block:^(void){ stat1;stat2; } ] (这里就是上面提到的匿名block)
三,基本用法
1,add(2,3);//输出5
2,Block在oc中也是一个对象,可以对其进行release,copy,retain等操作。
如[add copy];
3,闭包特性
void testBlock(){
int a =1;
int b = 3;
int(^sum)(void) = ^{
return a + b;
};
printf(@"%d",sum);//输出是4;
a = 2;
printf(@"%d",sum);//输出仍是4;
};
原因:a和b都是自由变量或者local变量,在block中是只读的。在定义sum的时候,编译器已经对a和b做了一个const拷贝,不能在sum中修改a的值并保存。
4,如果想在block中修改外部自由(local)变量,一是可以引用_block修饰,二是可以用static改成全局变量。这时自由变量是可写的
void testBlock(){
_block int a =1;
int b = 3;
int(^sum)(void) = ^{
return a + b;
};
printf(@"%d",sum);//输出是4;
a = 2;
printf(@"%d",sum);//输出仍是4;
};
四,blocks的应用
1,用作多线程的代码单元(GCD),多核并行编程。
2,用作某个函数调用完成后的回调函数。如UIView动画,Notification。
Block作为回调函数比传统回调函数的优越性:
在函数调用的时候,将block作为一个参数传递,使得代码紧凑,结构清晰。
例如:
block之前,
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
// Notification-handling code goes here.
}
block之后,
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification
object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
// Notification-handling code goes here.
}];
}
3,允许访问本地变量,这样可以避免通过结构体将本地变量封装后传递给回调函数。最为典型的就是异步数据下载后,更新ui。
NSString* parameter = [self getSomeParameter];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{NSString* result
= [self fetchResultFromWebWithParameter:parameter];
dispatch_async(dispatch_get_main_queue(), ^{[self updateUIWithResult:result]; // 能直接使用上层block中的变量result,只读的。所以说可以直接使用局部变量});
});
作者:
董月峰
时间:
2014-4-2 11:37
block要掌握的东西
1.如何定义block
int (^sumBlock)(int, int);
void (^myBlock)();
2.如何利用block封装代码
^(int a, int b) {
return a + b;
};
// void (^myblock)() = ^(){
// NSLog(@"------1---");
// NSLog(@"------2---");
// };
// 若block没有形参,可以省略^后面的()
// 定义了一个没有形参,没有返回值的block
void (^myblock)() = ^{
NSLog(@"------1---");
NSLog(@"------2---");
};
3.block访问外面变量
1》block内部可以直接访问外部变量
2》默认情况下,block内部不可以修改外面的局部变量
3》给局部变量加深__block关键字,这个局部变量就可以在block内部修改
4.利用typedef定义block类型
typedef int (^MyBlock) (int, int);
// 以后就可以利用MYBlock这种类型来定义block变量
int a;
int b;
int a,b;
MyBlock b1,b2;
b1 = ^(int a, int b) {
return a + b;
};
b2 = ^(int a, int b) {
return a * b;
};
MyBlock b3 = ^(int a, int b) {
return a - b;
};
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2