简介
Block是将函数
及其执行上下文
封装起来的对象
。可以保存一段代码,在需要的时候调用。
声明
格式为: 返回值类型(^Block名字)(参数列表);
如:
// 无参无返回
void (^aBlock)(void);
// 无参有返回
int(^aBlock)(void) ;
// 有参有返回
NSString* (^aBlock)(NSString * x, int y);
// 无参有返回
NSString* (^aBlock)(void);
- block属性,使用copy修饰,最好不用strong。
@property(nonatomic,copy)NSString* (^ablock)(void);
- 自定义Block类型
typedef void (^Block)(void);
typedef int (^MyBlock)(int a, int b);
typedef void(^ConfirmBlock)(BOOL isOK);
typedef NSString *(^AlertBlock)(NSInteger alertTag);
赋值
赋值格式为: Block变量名 = ^返回类型(参数列表){ 函数体 };
如:
// 无参无返回
self.aBlock = ^{
NSLog(@"... ...");
};
// 无参有返回
self.ablock = ^NSString *{
NSLog(@"dd");
return @"dd";
};
// 有参有返回
self.ablock = ^NSString *(int a) {
return @"vv";
};
// 有参无返回
self.aBlock = ^(NSString *x, int y){
NSLog(@"mmm");
};
block由其所属的类对象调用,指明要做什么。block中包含的是一段代码,含义是执行一些操作,具体什么操作,相当于给属性赋值,只是这里给block赋一段代码。
调用
由其所属的类对象调用。类似方法调用
如:
//无返回
self.ablock();
//有返回
NSString *result = self.ablock(2);
应用
在处理异步问题的时候,例如HTTP请求,有点像javascript
的回调,在得到回复的时候更新主线程,而不会占用主线程,比Delegate
逻辑好看多了;或者,当你要返回多个值又懒得创建一个类的时候。
1.传递数据(把数据传递出去、逆传)
- 在自己的.h中,声明带参数的block属性。
@interface PDMineVC : PDViewController
@property(nonatomic,copy)void (^rebackBlock)(NSString *flag);
@end
- 在.m中,调用block。
// 调用,把需要传递的信息 作为参数
self.rebackBlock(@"425");
- 在外界
类对象定义自己的block属性。
PDMineVC *vc = [[PDMineVC alloc] init];
vc.rebackBlock = ^(NSString *flag) {
NSLog(@"--%@",flag);
};
[self.navigationController pushViewController:vc animated:YES];
2.捕获变量
有两种方式:值传递、指针传递
- 值传递的情况
在声明Block之后、调用Block之前,对局部变量进行修改。调用Block后,局部变量值不变。
int temp = 100;
// 声明Block
void(^myBlock)() = ^{
NSLog(@"global = %d", temp);
};
temp = 101; // 修改变量的值
// 调用Block
myBlock();
// 调用后输出"temp = 100"
解释:声明Block的时候,只是把变量的值
保存进Block代码块中,所以调用Block时,打印的仍然是变量原来的值。
引用block 外的变量,block 默认是将变量的
值
复制到其数据结构中来实现访问的。
- 指针传递的情况
对于上一种情况,只需用__block
修饰变量即可,只要变量值改变,值就跟着改变。
__block int temp = 100;
解释:对于用 __block 修饰的外部变量引用,block 是复制其引用地址
来实现访问的。
注意:
不可以在Block中修改局部变量;
全局变量、static
静态变量,在Block中的值也会随修改而变。
3.保存一段代码
在本类中定义Block,本类对象在另一个类中调用Block。
4.block作为函数的参数
把block当成方法的参数使用
在外界写block的声明,在方法内部调用block。
例子
方法的声明
+(void)checkNetworkStatusOn:(void (^)(NSString * status))CallBack;
方法的定义
+(void)checkNetworkStatusOn:(void (^)(NSString * status))CallBack{
// ...
// blcok调用,传递信息
CallBack ? CallBack(@"网络处于断开状态") : nil;
}
方法的调用,并声明Block
[self checkNetworkStatusOn:^(NSString *status) {
NSLog(@"---->%@",status);
}];
// 定义带参的block类型,本类对象调用,参数来自本类对象
typedef void(^selectedHandler)(NSUInteger index,NSString *title);
// 声明方法,block作为参数
- (instancetype)initWithFrame:(CGRect)frame
titles:(NSArray *)titles
selectedHandler:(selectedHandler)handler;
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles selectedHandler:(selectedHandler)handler {
if ( [super initWithFrame:frame]) {
self.ablock = handler ; // 外界传入代码块,外界来决定做什么
}
return self;
}
5.block作为函数的返回值(少用)
block内存管理
如果对Block进行一次copy操作,那么Block的内存会被移动到堆
中,这时需要开发人员对其进行内存管理。
在Block存储在堆中时,如果在Block中引用了外面的对象,会该对象进行一次retain
操作。即使在Block自身调用了release
操作之后,不会release
该对象,这时会造成内存泄漏。
Person *pObject = [[Person alloc] init];
void(^myBlock)() = ^{
NSLog(@"------%@", pObject);
};
myBlock();
Block_copy(myBlock); // copy操作
// ...
Block_release(myBlock);
[pObject release];
// -->Person对象在这里无法正常被释放,因为其在Block中被进行了一次retain操作。
为了不对所引用的对象进行一次retain
操作,可以使用__block
来修饰对象
__block Person *pObject = [[Person alloc] init];
block循环引用
如果对象内部有一个Block属性,而在Block内部又访问了该对象,那么会造成循环引用。
解决:
-
__block
修饰
在对象的前面使用__block
来修饰,以避免Block对对象进行retain
操作。
__block Person *p = [[Person alloc] init];
-
弱指针
新创建一个弱指针来指向该对象,并将该弱指针放在Block中使用,这样Block便不会造成循环引用。
__weak typeof(Person) weakP = p;
void(^myBlock)() = ^{
NSLog(@"------%@", weakP);
};
这样虽然解决了循环引用,但是也容易涉及到另一个问题:
因为Block是通过弱引用指向了Person对象,那么有可能在调用Block之前,Person对象已经被释放。所以我们需要在Block内部
再定义一个强指针
来指向Person对象。
__weak typeof(Person) wp = p;
aBlock = ^(NSString *flag) {
__strong typeof(Person) sp = wp;
NSLog(@"%@", sp);
};
补充:
在ARC默认情况下,Block的内存存储在堆中,ARC会自动进行内存管理,程序员只需要避免循环引用即可。
在Block内部定义的变量,会在作用域结束时自动释放,Block对其并没有强引用关系,且在ARC中只需要避免循环引用即可,如果只是Block单方面地对外部变量进行强引用,并不会造成内存泄漏。
相关资料
http://www.jianshu.com/p/14efa33b3562 *
http://www.jianshu.com/p/649fca982c6e
http://www.jianshu.com/p/45557fbef2bf
https://www.jianshu.com/p/c389afedbce6 *
网友评论