block细节
- 如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】
- 如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】
block与链式编程
详见链式编程
block应用场景
- 存放代码,在本文件中定义,在其他文件调用,使用前需先判断block是否为空再执行
- 逆传传值
- block作为参数
- block作为返回值,通过...实现代码;遵循的是链式编程思想:可读性极高,把一些方法通过.连接起来.如make.top.equalTo(superview.mas_top).with.offset(padding.top)
// 调用模型中保存的代码
if (item.operationBlock) {
item.operationBlock();
}
/*逆传传值
传值给别人,首先得要拿到它
拿到ViewController
block:用于逆传,替代代理
1.在传递方(ModalViewController)声明block属性
2.在接收方(ViewController)定义block属性
3.需要传值,直接调用Block,把值当做block参数传递出去
*/
// block作为参数
// 方法中有没有block,就观察下有没有^,只要带了^,就是把block当做参数使用
// 把block当做参数使用的时候,什么时候调用Block,由内部决定.
// 开发场景:比如说有个类,有一段代码由外界决定,但是什么时候调用,却是由内部决定,可以使用把block当做参数.
void (^block)() = ^{
NSLog(@"调用了block");
};
// 动画场景,苹果知道做什么动画,什么时候执行动画,不需要我们管理,由苹果决定.
blcok内存管理
/*
block内存管理:ARC,非ARC
非ARC:
block如果没有访问外部变量,在全局区
block如果访问外部变量,在栈里面
block不要使用retain,不会把保持到堆里面
block在非ARC,只有使用copy,才会放到堆里面
// 非ARC没有强指针概念,默认基本变量,所以block访问外部变量是assign修饰,在栈区
ARC:
block访问外部变量,就在堆里面.
block可以使用copy,strong,建议使用strong.
block不要使用weak,assign
block是对象吗?是
*/
// 在ARC中不允许调用[super dealloc]
// ARC中不允许使用retain,release.
// 非ARC开发习惯,在非ARC中,如果使用成员属性,一般都是调用get,set方法,不会直接访问下划线成员属性
- (void)viewDidLoad {
[super viewDidLoad];
// block会对外界所有强指针给强引用一下
// 如何解决block强引用,尽量在block中使用弱指针
// __weak ModalViewController *weakSelf = self;
// typeof(参数):获取参数类型
__weak typeof(self) weakSelf = self;
_block = ^{
// 什么情况下,才需要定义强指针,如果Block有延迟操作或者异步线程处理时间,并且需要访问一些外部变量,最好把它定义成强指针;不再有强指针指向vc,vc会在block执行完后销毁
__strong ModalViewController *strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",strongSelf);
});
};
// 调用
_block();
}
// 如果block中访问的外部变量是局部变量,就是值传递,外界改了,不会影响里面.此时block在栈区
// 如果block中访问的外部变量是__block或者static修饰,或者全局变量,就是指针传递,block里面的值和外界同一个变量,外界改了,里面也会改.
block基础
// name:block类型别名
typedef void(^BlockName)();
/*
1.block声明:返回值(^block变量名)()
2.block定义:
3.block作用:
4.block类型
*/
// 1.声明没有返回值也没有参数变量名叫block
void(^block)();
// 2.定义block
// 定义一: 等号右边: ^返回值(){};
void(^block1)() = ^void(){
};
// 定义二: 定义block,不管有没有返回值都可以省略,如果有返回值,在代码块中一定要记得return
int(^block2)() = ^(){
return 1;
};
// 定义三:定义block,如果没有参数,可以省略括号
void(^block3)() = ^{
NSLog(@"%s",__func__);
};
// 3.block作用:保存一段代码
// 4.调用Block,才会进入对应保存代码块中
block3();
// 5.block类型:void(^)()
BlockName b = ^{ };
// inlineblock是block快捷方式