1 block基本概念
- block作用:保存一段代码
- block声明:
void(^block)(void)
- block定义:
1 方法定义
-(void)方法名:(返回类型(^)(参数))block名称;
- (void)action:(void(^)(UIView *tipView))action;
- (void)action:(void(^)(void))action;//如果没带参数就写void
2 属性定义
@property (nonatomic, copy) 返回类型(^block名称)(参数);
@property (nonatomic, copy) void(^action)(UIView *tipView);//带参
@property (nonatomic, copy) void(^action)(void);//不带参写void
3 变量定义
返回类型(^变量名)(参数类型) = ^(形参){
//do somting
}
- 变量定义的三种方式
// 方式1:
void(^block1)(void) = ^{
};
// 方式2:如果没有参数,参数可以隐藏,如果有参数,定义的时候,必须要写参数,而且必须要有参数变量名
void(^block2)(int) = ^(int a){
};
// 方式3 block返回值可以省略,不管有没有返回值,都可以省略
int(^block3)(void) = ^ {
return 2;
};
- block类型:int(^)(NSString *)
int(^block4)(NSString *) = ^(NSString *name) {
reture 2;
}
- block调用
block1();
- block代码块快捷方式:
inlineBlock
2 block开发使用场景
- 在一个方法中定义,在另外一个方法中调用
注:block如何声明,就如何定义成属性
@property (strong, nonatomic) void(^block)(void);
- 声明方式2:
//BlockType 类型别名
typedef void(^BlockType)(void);
@interface ViewController ()
@property (strong, nonatomic) BlockType block1;
@end
-
在一个类中定义,在另一个类中调用(常用方式)
-
block传值
3 block在MRC中内存管理
-
block是一个OC对象
-
如何判断当前文件是否MRC
1.dealloc 能够调用super,只有MRC才能调用super
2.能否使用retain,release,如果能用就是MRC -
ARC管理原则:只要一个对象没有被强指针修饰就会被销毁,默认局部变量对象都是强指针,存放到堆里面
-
MRC了解开发常识
1.MRC没有strong,weak,局部变量对象就是相当于基本数量类型
2.MRC给成员属性赋值,一定要使用set方法,不能直接访问下划线成员属性赋值 -
MRC中block内存管理
1.只要block引用了外部的局部变量,block放在栈里面
2.只要block没有引用外部的局部变量,block放在全局区里面
3.MRC里面只能使用copy修饰block,不能使用retain,因为使用retain,block还是在栈里面
4 block在ARC中内存管理
1.只要block没有引用外部的局部变量,block放在全局区里面
2.只要block引用的外部局部变量,block放在堆里面
3.block使用strong修饰,最好不要使用copy
5 block循环引用
-
理解iOS内存
iOS内存区域主要分为:栈区、堆区、全局区(静态区)、文字常量区、代码区
iOS几大内存区域 -
理解block在什么情况下会出现循环引用?
简单来说就是在堆上的对象与堆上的对象互相引用造成的环,就会引起循环引用。
这个概念对于理解循环很重要 -
理解oc中block存在在内存的位置
NSConcreteGlobalBlock
全局block,存储在数据区,不会引起循环引用的问题。(因为没有捕获外部变量)
NSConcreteStackBlock
存储在栈上的block,内存管理由系统处理,不会引起循环引用问题
NSConcreteMallocBlock
这种block在堆上,如果捕获了外部对象,则可能会引起循环引用的问题。 -
理解 block 只有捕获外部变量时,才会引用它。如果是内部新建一个,则没有任何问题
Strong-Weak Dance
通过demo来理解解决循环引用
#import "TestViewController.h"
@interface TestViewController ()
@property (strong, nonatomic) void (^block) (void);
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
__weak typeof(self) wSelf = self;
self.block = ^{
__strong typeof(self) sSelf = wSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",sSelf.view);
});
};
NSLog(@"%@",self.block);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.block();
}
- (void)test:(void(^)(int a))block {
}
- (void)dealloc {
NSLog(@"%s",__func__);
}
6 block值传递
- 如果是局部变量,block是值传递
- 如果是静态变量,全局变量,__block修饰的变量,block都是指针传递
int a = 5;
void(^block)(void) = ^{
NSLog(@"%d",a);
}
a = 3;
block();
7 block开发使用场景
-
参数传递
- 看有没有^,只要有^,把block当做参数
- 把block当做参数,并不是马上就调用block,什么时候调用,由方法内部决定
- 什么时候需要把block当做参数与使用:做的事情由外界决定,但是什么时候做由内部决定。
-
返回值
链式编程思想:把所有的语句用.号连接起来
- (ViewController *(^)(int))add {
__weak typeof(self) weakSelf = self;
return ^(int value) {
weakSelf.result += value;
return self;
};
}
ViewController *vc = [[ViewController alloc] init];
vc.add(5).add(5).add(5);
NSLog(@"%d",vc.result);
网友评论