block声明
// block声明:返回值(^block变量名)(参数)
void(^block)();
block的定义方式(三种)
// block定义:三种方式 = ^(参数){};
// 第一种
void(^block1)() = ^{
NSLog(@"调用了block1");
};
// 第二种 如果没有参数,参数可以隐藏,如果有参数,定义的时候,必须要写参数,而且必须要有参数变量名
void(^block2)(int) = ^(int a){
};
// 第三种 block返回可以省略,不管有没有返回值,都可以省略
int(^block3)() = ^int{
return 3;
};
// block快捷方式 inline
// <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
// <#statements#>
// };
block 调用
block1();
通过typedef声明一个block的类型
//FinishBlock:Block的类型名
typedef int(^FinishBlock)(int a,NSString *s);
//定义
FinishBlock myBlock1 =^(int a,NSString *s){
NSLog(@"myBlock1被调用了");
return 101;
};
//(3)block的调用
myBlock1(21,@"Block1");
注意:block的调用顺序:
1 block块 第一次运行的时候,不执行block块
2 block块执行的时机:调用block函数
block 使用方式
- 1.在一个方法中定义,在另外一个方法调用(不推荐使用,完全可以用方法的形式代替)
- 2.在一个类中定义,在另外一个类中调用(推荐使用,block的作用就是保存一段代码)
- 3.注意:在编写程序时,不要一味着想用block而用block,关键是看是否用block编写是否为最佳形式
block传值
- 1.传值的核心思想:只要能拿到对方(类或对象)就能传值
- 2.传值包括两种:
- 顺传:给需要传值的对象,直接定义属性就能传值
- 逆传:用代理,block,就是利用block去代替代理
//简单demo
#import "ViewController.h"
#import "ModalViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
ModalViewController *modalVc = [[ModalViewController alloc] init];
modalVc.view.backgroundColor = [UIColor brownColor];
modalVc.block = ^(NSString *value) {
NSLog(@"%@",value);
};
// 跳转
[self presentViewController:modalVc animated:YES completion:nil];
}
#import <UIKit/UIKit.h>
@interface ModalViewController : UIViewController
//设置一个block属性
@property (nonatomic, strong) void(^block)(NSString *value);
@end
#import "ModalViewController.h"
@interface ModalViewController ()
@end
@implementation ModalViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 传值给ViewController
// @"123"
if (_block) {
_block(@"123");
}
block内存管理机制
block是不是一个对象?是一个对象
如何判断当前文件是MRC,还是ARC
1.dealloc 能否调用super,只有MRC才能调用super
2.能否使用retain,release.如果能用就是MRC
ARC管理原则:只要一个对象没有被强指针修饰就会被销毁,默认局部变量对象都是强指针,存放到堆里面
MRC了解开发常识:1.MRC没有strong,weak,局部变量对象就是相当于基本数据类型
MRC给成员属性赋值,一定要使用set方法,不能直接访问下划线成员属性赋值
总结:只要block没有引用外部局部变量,block放在全局区
-
MRC:管理block
- 只要Block引用外部局部变量,block放在栈里面.
- block只能使用copy,不能使用retain,使用retain,block还是在栈里面,会被销毁
- ARC:管理block
- 只要block引用外部局部变量,block放在堆里面
- block使用strong.最好不要使用copy
- 补充:NSString也是最好使用strong,最好不要使用copy
block变量传递
// 如果是局部变量,Block是值传递
// 如果是静态变量,全局变量,__block修饰的变量,block都是指针传递
int a=3;
- (void)viewDidLoad {
[super viewDidLoad];
//__block int a = 3;
// int a = 3;
// static int a =3;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 5;
block();
}
block作为参数使用
- (void)viewDidLoad {
[super viewDidLoad];
// 创建计算器管理者
CacultorManager *mgr = [[CacultorManager alloc] init];
[mgr cacultor:^(NSInteger result){
result += 5;
result += 6;
result *= 2;
return result;
}];
NSLog(@"%ld",mgr.result);
}
#import <Foundation/Foundation.h>
@interface CacultorManager : NSObject
@property (nonatomic, assign) NSInteger result;
// 计算
- (void)cacultor:(NSInteger(^)(NSInteger result))cacultorBlock;
@end
#import "CacultorManager.h"
@implementation CacultorManager
- (void)cacultor:(NSInteger (^)(NSInteger))cacultorBlock
{
if (cacultorBlock) {
_result = cacultorBlock(_result);
}
}
@end
block作为返回值使用
- (void)viewDidLoad {
[super viewDidLoad];
/*
链式编程思想:把所有的语句用.号连接起来,好处:可读性非常好
*/
CalculatorManager *mgr = [[CalculatorManager alloc] init];
mgr.add(5).add(5).add(5).add(5);
NSLog(@"%d",mgr.result);
#import <Foundation/Foundation.h>
@interface CalculatorManager : NSObject
@property (nonatomic, assign) int result;
- (CalculatorManager *(^)(int))add;
@end
}
#import "CalculatorManager.h"
@implementation CalculatorManager
- (CalculatorManager *(^)(int))add
{
return ^(int value){
_result += value;
return self;
};
}