block数据类型
block
数据类型的变量中专门存储一段有限定代码,这段代码可以有参数,可以有返回值
block
在声明时,必须指定这个代码段是否有参数,是否有返回值,制定完只能存储这样的代码
返回值类型 (^变量的名称)(参数列表);
void (^myBlock1)();//无返回值无参数名称为myBlock1
int (^myBlock2)();//返回值为int无参数名称为myBlock2
int (^myBlock3)(int num1,int num2);
^返回值类型(参数列表){
代码段;
};
myblock1 = ^void(){
NSLog(@"Hello!");
};
//也可以声明的时候初始化
void (^myBlock1)() = ^void(){
NSLog(@"Hello!");
};
//调用
myblock1();
//block作为函数的参数
void test(void (^block1)())//在小括号里声明指定格式的block,可以用typedef简化
{
NSLog(@"Hello!");
block1();
}
//block作为函数返回值
void (^)() test()
{
void (^block1)()=^{
NSLog(@"Hello!");
};
return block1;
}
- 代码段的返回值可以省略,或者没有参数也可以省略,声明
block
变量的返回值不可省略
void (^myblock1)() = ^{
NSLog(@"Hello")
}
block
块访问外部变量的问题:可以取定义在外部的局部和全局变量,可以修改全部变量,但不能修改局部变量- 如果定义的局部变量想要在
block
中修改,定义时加__block
的修饰符 block
与函数的异同点:都是封装一段代码,block
是一个数据类型,block
可以声明变量,block
可以作为参数和返回值
Block的本质
block
在底层上是一个结构体,内部有一个isa
指针,指向block
所属的类,其父类最终指向NSObject
,所以可以把block
看做对象
block
也可以理解为函数指针
Block的类型
block
有三种类型:_NSConcreteGlobalBlock
(全局block
),_NSConcreteStackBlock
(栈block
),_NSConcreteMallocBlock
(堆block
),分别储存在data
区,栈区,堆区,他们的类型由创建方式以及创建时候捕获的变量类型决定
- 不使用外部变量的
block
是全局block
- 使用外部变量并且未进行
copy
操作的block
是栈block
- 对栈
block
进行copy
操作,就是堆block
__block
修饰的变量可以在block
里面进行改变,从栈copy
到堆
所以一般是使用全局、静态、__block
,才可以修改外部变量的值
Block循环引用问题
weakSelf
是为了block
不持有self
,避免Retain Circle
循环引用。在Block
内如果需要访问self
的方法、变量,建议使用weakSelf
。strongSelf
的目的是因为一旦进入block
执行,假设不允许self在这个执行过程中释放,就需要加入strongSelf
。block
执行完后这个strongSelf
会自动释放,没有不会存在循环引用问题。如果在Block
内需要多次 访问self
,则需要使用strongSelf
。
__weak typeof(self) weakSelf = self;
__strong typeof(self) strongSelf = weakSelf;
typeof(self)是C语言函数,返回其数据类型
block的定义
//typedef 定义有参数有返回值的block
typedef int (^MyBlock)(int a, int b);
//block 修饰 作为属性
@property (nonatomic, copy) MyBlock threeBlock;
@weakify、@strongify等效
@weakify(self)
@strongify(self)
__weak typeof(self) weakSelf = self;
__strong typeof(self) strongSelf = weakSelf;
参考文章
这个文章写得非常优秀,可以参考
ios之Block的详细使用和具体说明