标签:
基本使用:作用就是用来保存一段代码块
在一个方法定义,在另外一个方法去调用(用的少,可以用定义方法替代)
一般在 在一个类中定义,在另外一个类中去调用 用的比较多
-------------------------------------------------------------------------------------------Make by - ljw 转载请注明出处---
定义的几种方式:
方式一: 等号 = ^(参数){ block代码块 }
注意点:如果block带有参数,在定义的时候,一定要有参数,并且变量名不能省略
void(^block1)(int) = ^(int a){
NSLog(@"调用了block%d",a);
};
方式二: 如果没有参数,参数可以省略
方式三: 等会右边 = ^返回值(参数),返回值可以省略,不管有没有返回值,都可以省略
注意:如果Block有返回值,block代码块必须要有返回值
int(^block3)() = ^int{
return 1;
};
-------------------------------------------------------------------------------------------
调用block1:查看block保存的代码
block快捷方式:inline
// <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
// <#statements#>
// };
案例:点击cell,作出相应的动作
在cell里面利用block保存代码
1.在cell模型声明block属性
@property (nonatomic, strong) void(^block)();
2.在模型里面保存代码
// 打电话
CellItem *item = [CellItem cellItem];
item.title = @"打电话";
// 定义block给它
item.block = ^{
NSLog(@"打电话");
};
3.点击cell调用block
// 点击cell就会调用
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CellItem *item = self.items[indexPath.row];
if (item.block) {
item.block();
}
}
block传值:
顺传:定义属性
逆传:代理, block替代代理
传值万能步骤:A传值B,A拿到B 就能传值 B传值A,拿到B就能传值
方式一:代理
方式二:block
1.在传递方头文件声明block属性
@property (nonatomic, strong) void(^block)(NSString *value);
2.在.m文件触发事件传值(参数)
判断一下是否有block
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 传值:
if (_block) {
_block(@"123");
}
3.接收方拿到传递方,拿到block接收值
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
ModalViewController *modalVc = [[ModalViewController alloc] init];
modalVc.block = ^(NSString *value){
NSLog(@"利用了block,接收到值%@",value);
};
block内存管理
如何判断当前项目是ARC,还是非ARC
1.在ARC中,不允许调用retain,release,retainCount
2.重写dealloc,ARC中不能调用[super dealloc]
怎么进入非ARC环境 : 点击工程文件 -> buildSetting -> ARC
在非ARC开发注意点:访问属性,一定要使用get,set方法,不能直接使用下划线
block是对象吗?
是!官方文档有说明.可以放到数组或者字典中使用!
看官方文档
(搜索working with Blocks)
非ARC block内存
只要block访问了外部变量,生命周期不是全局的(是否在代码块里面),就存放在栈里面
生命周期是全局的,block就存放在全局区
只要Block没有访问外部变量,就放在全局区
非ARC内存管理:
block在非ARC中必须要使用copy
Block为什么用copy,在非ARC
在非ARC环境下,retain相当于strong,为什么block不用retain
因为在非arc中,是不会存放到堆里面,过了代码块就会被释放.再访问就会坏内存访问报错
非ARC
是没有strong的(强指针)的
不能用下划线直接访问成员属性的
在非ARC开发注意点:访问属性,一定要使用get,set方法,不能直接使用下划线
----------------------------------------------------------------------------------------------------------------------------------
ARC内存管理:
ARC下,默认一个局部变量就是一个强指针,防止一创建就释放
block访问了一个局部变量,就会放到堆里面
能用strong就用strong,因为copy内部会做很多事情
只要访问了一个外部变量,,生命周期不是全局的,只会放在堆里面
只要访问了一个外部变量,,生命周期是全局的,只会放在全局区
把一个控制器modal出来,再dismiss会把控制器销毁
只要在block代码块里面使用了self强引用就会导致循环引用
注意:只要在block的代码中,访问外部强指针对象,就会把对象强引用
1 - (void)viewDidLoad {
2 [super viewDidLoad];
3 int a = 2;
4
5 // 注意:只要在block的代码中,访问外部强指针对象,就会把对象强引用
6 /// 解决循环引用
7 // block
8 __weak typeof(self) weakSelf = self;
9
10 _block = ^{
11
12 // 定义强指针的self
13 __strong typeof(self) strongSelf = weakSelf;
14
15 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
16
17 NSLog(@"%@",strongSelf);
18
19 });
20
21
22 NSLog(@"%d",a);
23
24 };
25
26 _block();
27 }
block在定义的时候就把值传进去了
值传递: 访问局部变量
指针传递:访问生命周期全局变量
被__block修饰的局部变量,就是指针传递
bock开发场景:参数使用
1.封装一个类的时候,有些时候,怎么去做由外界决定,但是由内部决定什么时候调用,把block当做一个参数去使用.
动画block:做什么样的动画由我们决定,但是什么时候调用由系统决定.
block当做返回值
链式编程思想: 把所有的方法调用全部通过.语法连接起来,好处:可读性非常好
mgr.add(5).add(5);
其实是分两步走,先调用mgr.add的getter,返回一个block.再跟着()实现这个block
- (CalculatorManager *(^)(int))add;
- (CalculatorManager *(^)(int))add
{
return ^(int value){
_result += value;
return self;
};
}
- (void)add;
实现:mgr.add()
想实现小括号,必须是两步走,先实现block的getter
—>- (void *(^)(int))add;
实现:mgr.add(5).add(5)
想继续点下去,就必须得有一个返回值
—>- (CalculatorManager *(^)(int))add;
题外话:装逼写法:block实现里面后面直接跟着调用
^{
NSLog(@"调用");
}();
学习笔记-block基本使用
标签:
原文地址:http://www.cnblogs.com/ljwios/p/5467826.html