iOS三大回调方式:目标动作回调,委托回调,代码块回调。block最大的用处就是回调,可以代替委托。
Block:一段代码,相当于函数指针,指向一段代码的内存地址。可以访问外部作用域的变量,可用于回调。可以作为参数传递。
1.基础
1)定义
格式:(ReturnType) (^BlockName) (Args , Args2){}1
2
3
4int (^addBlock)(int a,int b) = ^(int a,int b){
return a + b;
};
addBlock(2,3);
定义一个名为addBlock的变量,需要两个参数。1
2
3void (^someBlock)() = ^{
//the block of code
};
Block无参数时,可以省略括号^{}.
2)创建块类型typedef1
typedef int (^EOCSomeBlock) (BOOL flag, int value);
创建了一个名为EOCSomeBlock的类型1
2
3EOCSomeBlock block = ^(BOOL flag , int value ){
//some code
}
定义一个EOCSomeBlock类型的变量block
3)block 修饰可读写变量
block块内部可以获取在其声明范围的变量,但是只能读不能写。声明变量的时候加上block修饰,就可以在块内修改该变量了。block代码分配在栈上,__block 将变量分配到堆上。1
2
3
4
5
6
7
8
9//简写,相当于[NSArray arrayWithObjects:[NSNumber numberWithInt:3],[NSNumber numberWithInt:5], nil];
NSArray *array = @[@3,@5,@6,@8,@13];
__block NSInteger count = 0;
//NSArray 枚举数组中每项
[array enumerateObjectsUsingBlock:^(NSNumber *number, NSUInteger idx,BOOL *stop){
if ([number compare:@2] == NSOrderedAscending) {
count++;
}
}];
4)weak 避免引用循环
将块定义在类的实例方法中,块内可以访问类的所有实例变量,还可以使用self变量。
在内存分配管理中,会有一个强指针指向block ,而block内部的self本身也有一个强指针指向block,就造成了强引用循环,双方都不能释放。
使用weak创建弱引用变量,该变量指向的对象,当没有指针指向时,会设置为nil ,避免了引用环(retain cycle)1
2
3
4__weak MyClass *weakSelf = self;
[self.myBlocks addObject:^ {
[weakSelf doSomething];
}];
2.使用场景
1)枚举(数组,字典枚举每项),视图动画,排序
2)通知Notification
3)错误处理
4)多线程GCD(重要功能)
5)代替委托(delegate)功能