Block 一些基础知识
1.Block 使用哪种修饰符?
Block 使用 copy 关键字,因为在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区
2.Block 循环引用的问题
self 持有 block, 并且 block 里使用 self 会导致循环引用.
解决方法:参照 AFNetworking 的写法
block 外部使用
__weak typeof(self) weakSelf = self;
内部使用
__strong typeof(weakSelf) strongSelf = weakSelf;
3.Block 存储域
- NSConcreteStackBlock, 栈
- NSConcreteGlobalBlock, 程序的数据区域
- NSConcreteMallocBlock, 堆
那么什么时候栈上的 Block 会复制到堆呢?
- 调用 block 的 copy 实例方法时
- Block 作为函数返回值时
- 将 Block 赋值给附有 __strong 修饰符 id 类型的类或 Block 类型成员变量时
- 在方法名中含有 usingBlock 的 Cocoa 框架方法或 Grand Central Dispatch 的 API 中传递 block 时
具体代码:
block 用来保存一段代码
block 的标志:^
block 跟函数很像:
1).可以保存代码 2).有返回值 3). 有形参
temp1:没有返回值、没有形参的 block
如果 block 没有形参,可以省略 ()
void(^myblock)() = ^{
NSLog(@"----------");
NSLog(@"----------");
};
// 利用 block 变量调用 block 内部的代码
myblock();
temp2:有返回值,有形参
int (^sumblock)(int,int) = ^(int a,int b){
return a+b;
};
//返回值
int c = sumblock(1,1);
NSLog(@"%d",c);
temp 3:用一个 block 输出 n 条横线
void (^lineblock)(int) = ^(int n){
for (int i = 1; i < n; i++) {
NSLog(@"-------");
}
};
//无返回值,加 int 类型的参数
lineblock(5);
temp 4:
__block int a = 10;
void (^block)();
block = ^{
/*
block 内部可以访问外面的变量
默认情况下,block 内部不能修改外面的局部变量
给局部变量加上 __block 关键字,这个局部变量就可以在block内部修改
*/
a = 20;
NSLog(@"%d",a);
};
block();
temp 5:使用 typedef 定义 block 类型
// 类型 + 变量
MyBlock sumBlock;
sumBlock = ^(int a,int b){
return a+b;
};
sumBlock(10,9);
//减法
MyBlock minusBlock;
minusBlock = ^(int a,int b){
return a - b;
};
minusBlock(10,9);
//乘法
MyBlock multipBlock;
multipBlock = ^(int a,int b){
return a * b;
};
multipBlock(10,9);
//除法
MyBlock divideBlock;
divideBlock = ^(int a,int b){
return a / b;
};
divideBlock(10,2);
NSLog(@"
%d
%d
%d
%d",sumBlock(10,9),minusBlock(10,9), multipBlock(10,9),divideBlock(10,2));
总结:
1.如何定义 block 变量
int (^sumBlock)(int,int);
void (^myBlock)();
2.如何利用 block 封装代码
^(int a,int b){
return a - b;
};
//没有参数
^(){
NSLog(@"-----");
}
//没有返回值
^{
NSLog(@"-----");
}
3. block 访问外面变量
1.block 内部可以访问外面的变量 2.默认情况下,block 内部不能修改外面的局部变量
3.给局部变量加上 __block 关键字,这个局部变量就可以在block内部修改
4.利用 typedef 定义 block 类型
typedef int(^MyBlock)(int,int);
//以后就可以利用 MyBlock 这种类型来定义 block 变量
MyBlock block;
MyBlock b1,b2;
b1 = ^(int a,int b){
return a+b;
};
MyBlock b3 = ^(int a,int b){
return a+b;
};