1.Block基本用法:
block声明
返回值(^block变量名)(参数)
void(^block)();
block定义
//第一种
void(^block1)() = ^{
};
// 第二种,如果没有参数,参数可以隐藏,如果有参数,必须写,而且必须要有参数变量名
void(^block2)(int) = ^(int a){
};
// 第三种,不管有没有返回值,都可以省略
int(^block3)() = ^int{
return 3;
};
-
block调用
block1();
2.Block别名:
// 类型别名:BlockType
typedef void(^BlockType)();
3.定义为属性
// block如何声明,就如何定义成属性
@property (nonatomic, strong) void(^block)();
4.应用地点
- Block可以在一个方法中定义, 在另外一个方法调用
- Block可以在一个类中定义, 在另外一个类中调用
5.Delegate传值
5.1.头文件中生成协议,声明代理,
@protocol ModalViewControllerDelegate <NSObject>
@optional
// 设计方法:想要代理做什么事情
- (void)modalViewController:(ModalViewController *)modalVc sendValue:(NSString *)value;
@end
@interface ModalViewController : UIViewController
@property (nonatomic, weak) id<ModalViewControllerDelegate> delegate;
@end
5.2.m文件中,传值给ViewController
if ([_delegate respondsToSelector:@selector(modalViewController:sendValue:)]) {
[_delegate modalViewController:self sendValue:@"123"];
}
5.3.想要得到值的控制器中,遵循协议,成为代理,重写代理方法
@interface ViewController ()<ModalViewControllerDelegate>
modalVc.delegate = self;
// 重写代理方法
- (void)modalViewController:(ModalViewController *)modalVc sendValue:(NSString *)value{
}
6.Block传值
6.1.头文件中声明Block属性
@property (nonatomic, strong) void(^block)(NSString *value);
6.2.m文件中,传值给ViewController
if (_block) {
_block(@"123");
}
6.3.想要得到值的控制器中,定义Block
ModalViewController *modalVc = [[ModalViewController alloc] init];
modalVc.block = ^(NSString *value) {
NSLog(@"%@",value);
};
7.Block是不是对象?
- 答案是肯定的。
8.MRC中Block内存管理
- Block引用外部局部变量在栈,否则在全局区。
- Block只能用copy不能用retain,用copy才在堆中。
9.ARC中Block内存管理
- Block只要引用外部局部变量就在堆, 否则在全局区。
- Block最好使用strong,不用copy。他们的结果是相同的,但是copy的内部处理要比strong麻烦得多,长此以往性能较低。
10.由Block引起的内存泄漏
10.1.block循环引用场景:
- self强引用了block,block里面也强引用了self(block会自动把block块内的强指针强引用):
@property (nonatomic, strong) void(^block)();
_block = ^(){
//_name相当于 self -> name, 所以还是有self的
_name = @"123";
};
- 解决方案
__weak typeof(self) weakSelf = self;
_block = ^(){
weakSelf.name = @"123";
};
10.2.因为block,self不被销毁场景:
- 当其他对象(可能是全局变量)强引用了block,block中又强引用了self。也会导致self不能被销毁,但这个不是循环引用。
- 解决方案:
__weak typeof(self) weakSelf = self;
11.然而有时候,block中用weakSelf不安全。为什么?
__weak typeof(self) weakSelf = self;
- 因为如果block中有一个延迟执行的block,block中又使用了weakSelf。执行时候self很可能已经被销毁(block里面对他是弱引用)。
- 解决方案
__strong typeof(weakSelf) strongSelf = weakSelf;
12.Block使用场景
12.1.Block变量传递
- 局部变量, 是值传递
- 静态变量,全局变量,__block修饰的变量, 都是指针传递
__block int a = 3;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 5;
block();
12.2.Block作为参数传递
- (void)cacultor:(NSInteger (^)(NSInteger))cacultorBlock{
if (cacultorBlock) {
_result = cacultorBlock(_result);
}
}
CacultorManager *mgr = [[CacultorManager alloc] init];
[mgr cacultor:^(NSInteger result){
result += 5;
result += 6;
result *= 2;
return result;
}];
12.3.Block作为返回值
CalculatorManager *mgr = [[CalculatorManager alloc] init];
mgr.add(5).add(5).add(5).add(5);
- (CalculatorManager *(^)(int))add{
return ^(int value){
_result += value;
return self;
};
}