这只是我在学习过程中的一些认识, 可能有错误或者不完善的地方, 希望大咖们指点以下,在此先表示感谢啦!
Block封装保存一段代码,可以在任何时候任何地方使用
● Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。
● 苹果官⽅方建议尽量多用block。在多线程、异步任 务、集合遍历、集合排序、动画转场⽤的很多
Blocks和函数指针对⽐
相同点: 1.都可以保存代码
2.都可以有返回值
3.有形参
4.调用方式一样
不同点: 函数指针在运行前就固定好;
block在运行过程中封装代码块
● 定义函数指针
int sum(int a,int b)
{
return a + b;
}
//调用
int (*p)(int, int) = sum;
int d = p(10,12);
● 定义Block
int (^SumBlock)(int,int);
● 调用Block
SumBlock(10, 20);
1.如何利用block定义变量:
(1)带参数和返回值
int (^SumBlock)(int, int);
(2)不带参数和返回值
void (^ MulBlock)();
2.如何利用block封装代码:
(1) ^(int a, int b){
return a + b;
}
(2) ^{
return a * b;
}
3. block访问外部变量
Block内部可以访问局部(外面的)变量,默认情况下不能修改。
int sum = 10;
int (^MyBlock)(int) = ^(int num) {
sum++;//编译报错
return num * sum;
};
如果要修改就要给局部变量加关键字:__block
__block int sum = 10;
4. 利用typedef定义block类型
/**
* typedef: 给一个已有的类型起别名 -> 类型
* SumBlock是类型
* @param num1
* @param num2 可以不带参数,但是带上方便以后用
*
* @return
*/
typedef int (^SumBlock)(int num1,int num2);
//以后就可以用SumBlock类型来定义block变量,比较方便
(1)SumBlock a;
(2)SumBlock b1, b2;
b1 = ^(int a, int b){
return a + b;
}
(3)SumBlock b2 = ^(int a, int b){
return a + b;
}
a1(2, 3);//调用
5. 将block作为参数
int result = [self testFunction:^int(int m, int n) {
return m * n + 5;
}];
NSLog(@"result: %d",result);
//方法
- (int)testFunction:(GetSumBlock)block
{
int sum2 = block(4,5);
return sum2;
}
------------------MRC环境中-----------------------
使用局部变量:a到block块中,为了在block中能够使用这个变量,将a拷贝放到常量区域
// int a = 10;
如果访问局部对象,为了在block中能够使用这个对象,引用计数值加一
注意:如果使用__block修饰,计数值则不加一
__block NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"张三",@"李四",@"王五", nil];
[button addTapBlcok:^(UIButton *button){
// a = 90;
NSString *str = [array objectAtIndex:2];
NSLog(@"str:%@",str);
}];
[array release];
-----------------------------------
block对全局变量的影响:
block在访问全局变量、方法的时候,会将这个变量对应的对象计数值加一
block -> self -> self.view -> button -> block
解决方式:使用__block修饰self
总结:在MRC环境中__block的作用:
(1)可以在block中修改变量值
(2)block内部访问属性的时候,可以使用__block修饰,避免计数值加一(解决循环引用问题)
------------------ARC环境中-----------------------
__block:(1)可以让局部变量在block中修改数据
循环引用: self -> self.view -> button -> block -> self
在MRC情况中的解决方式:
__block SecondViewController *this = self;
在ARC环境中的解决方法:
// strong weak
__weak SecondViewController *weakThis = self;
[button addTapBlcok:^(UIButton *button){
在调用方法的时候,解决了循环引用问题
// [weakThis test];
//weakThis无法访问当前的属性
__strong SecondViewController *strongThis = weakThis;
strongThis->_index = 20;
NSLog(@"%ld",strongThis->_index);
[strongThis test];
}];
- (void)test {
NSLog(@"test");
}