定义
(1)Block是OC中的一种数据类型,在iOS开发中被广泛使用
(2)^是Block的特有标记
(3)Block的实现代码包含在{}之间
(4)大多情况下,以内联inline函数的方式被定义和使用
(5)Block与C语言的函数指针有些相似,但使用起来更加灵活
n示例
void(^demoBlock)() =^ {
NSLog(@"demoBlock");
};
int(^sumBlock)(int, int) =^(int x, int y) {
return x +y;
};
n格式说明:
n(返回类型)(^块名称)(参数类型)=^(参数列表){代码实现};
n如果没有参数,等号后面参数列表的()可以省略
Block可以使用在定义之前声明的局部变量
int i = 10;
void(^myBlock)() =^{
NSLog(@"%d", i);
};
i = 100;
myBlock();
输出 :10;
要使输出为100 ,在int i= 10 前加上__block
n注意:
(1)在定义Block时,会在Block中建立当前局部变量内容的副本(拷贝)
(2)后续再对该变量的数值进行修改,不会影响Block中的数值
(3)如果需要在block中保持局部变量的数值变化,需要使用__block关键字
(4)使用__block关键字后,同样可以在Block中修改该变量的数值
Block
可以
被当做参数直接传递
NSArray *array= @[@"张三",@"李四",@"王五",@"赵六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL*stop) {
NSLog(@"第 %d 项内容是 %@",(int)idx, obj);
if ([@"王五"isEqualToString:obj]) {
*stop = YES;
}
}];
说明:遍历并
NSLog
()
array
中的内容,当
obj
为
"
王五
"
时
停止
遍历
-------------------------
注意,默认情况下,Block外部的变量,在Block中是只读的!
BOOL flag = NO;
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if([@"王五" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
flag = YES; // 编译错误!!!
}
}];
如果要修改Block之外的局部变量,需要使用__block关键字
================
可以使用typedef定义一个Block的类型,便于在后续直接使用
typedef double(^MyBlock)(double, double);
MyBlock area = ^(double x, double y) {
return x * y;
};
MyBlock sum = ^(double a, double b) {
return a + b;
};
NSLog(@"%.2f", area(10.0, 20.0));
NSLog(@"%.2f", sum(10.0, 20.0));
说明:
(1)typedef是关键字用于定义类型,MyBlock是定义的Block类型
(2)area、sum分别是MyBlock类型的两个Block变量
==================
尽管,
typedef
可以简化
Block
的定义
,
但在实际开发中并不会频繁使用
typedef
关键字
这是因为
Block
具有非常强的灵活性,尤其在
以参数传递
时,使用
Block
的目的就是为了立即使用
官方的数组遍历方法声明如下:
-(void)enumerateObjectsUsingBlock:(void(^)(id obj, NSUIntegeridx, BOOL*stop))block;
而如果使用
typedef
,则需要:
(1)
typedef
void(^
EnumerateBlock
)(id
obj
,
NSUInteger
idx
, BOOL*stop);
(2)- (void)enumerateObjectsUsingBlock:(
EnumerateBlock)block;
而最终的结果却是,除了定义类型之外,EnumerateBlock并没有其他用处
===================
iOS中使用Block的场景
(1)遍历数组或者字典
(2)视图动画
(3)排序
(4)通知
(5)错误处理
(6)多线程
(7)……
提示:在Block内部,如果碰到self,最好能够思考一下