//bolck:一块代码.声明block类型的指针是指向一块代码,而不是一个对象
//block:闭包和匿名函数在OC中的实现
创建类型有多种:
1.无返回值无参数
2.无返回值有参数
3.有返回值有参数(有返回值要接收)
创建方式有3种: 格式:(变量名)(参数)
1.声明和创建分开 调用时必须有()
//第一种方式:声明一个无参数无返回值类型的block指针
//1.1声明和创建分开block
void(^block1)(void);
//创建一个block (无参数无返回值类型的block)
block1 = ^(void){
//block的创建就类似于方法,同样只有调用才会执行block块中的代码
NSLog(@"***我执行了***");
};
//block调用----即没有参数必须加()
block1();
//1.2声明和创建一起
//注意:当我们的参数为void的时候,声明可以忽略声明中的void,创建时可以省略(void)
void(^block2)() = ^{
NSLog(@"---我是一个省略(void)参数的block");
};
block2();
//1.3:宏定义方式
MyBlock blocck3;
blocck3 = ^ {
NSLog(@"我是重定义的");
};
blocck3();
2.声明和创建一起 (注意:当我们的参数为void的时候,声明可以忽略声明中的void,创建可以忽略(void))
//第二种方式:有一个参数无返回值类型的block指针
void(^block4)(int a,int b);//等价于void (^block4)(int ,int )
block4 = ^(int a,int b){
NSLog(@"%d + %d = %d",a,b,a+b);
};
block4(1,3);
//多个参数之间逗号隔开
Plus block5 = ^(int a,int b){
NSLog(@"从定义后的加法%d+%d=%d",a,b,a+b);
};
block5(3,4);
3.宏定义方式:在接口之前声明
typedef void(^别名)(参数,参数)
//给数据类型起别名----定义一个新的数据类型
//1.写像声明一个变量的代码
//2.将变量名改为你想要的别名
//3.语句前加上typedef
//给void(^)(void)类型的block指针起别名
typedef void (^MyBlock)(void);
别名block;
block = ^ {block code};
block (参数);
//第三种方式:有返回值多个参数的block类型指针
NSString * (^block6)(int,NSString* name);
block6 = ^(intage,NSString* name){
return [NSString stringWithFormat:@"我叫%@,%d岁",name,age];
};
//有返回值定义要接收
NSString *info = block6(18,@"翠花");
NSLog(@"---%@----",info);
Info block7 = ^(intage,NSString* name){
return[NSString stringWithFormat:@"== my name is %@,%d age ==",name,age];
};
NSString *new = block7 (2,@"baby");
NSLog(@"%@",new);
block_cycle
- (void)viewDidLoad {
[super viewDidLoad];
self.objc= [[NSObject alloc] init];
void(^block)(void) = ^{
};
Block_copy(block);
Block_release(block);
block();
}
//block的声明用copy:因为我们的block是声明在栈上,如果用retain,那么block依旧在栈上,当方法结束执行后,栈上就会被释放.所以我们要copy到堆上,堆内存有我们自己管理,不会被随意释放
//栈上copy到堆上手动管理不会被随意释放
@property (nonatomic,copy) MyBlockblock;
使用局部变量以防止出现循环引用
//**如果我们在block(用copy描述属性的block)中用到self,会导致block对视图控制器(self), --->retain会导致循环引用(我们当前的视图控制器无法释放)
//解决办法:__block SecondViewController * vc = self;
__block SecondViewController *vc =self;
//为了防止循环引用声明一个局部的视图控制器 == self
//对于成员变量也可以声明局部变量对其进行接收在对局部变量进行操作即可
//**如果我们在block(用copy描述属性的block)中用到self,会导致block对视图控制器(self), --->retain会导致循环引用(我们当前的视图控制器无法释放)
//解决办法:__block NSObject * obc = _obje;
__blockNSObject* obc =_obje;
#pragma mark ==对非基本数据类型的影响
/*
block对于非基本数据类型的影响
对于没有__block修饰的局部非基本数据类型的变量,block内会对其进行浅copy,也就是说,block内外的people对象不是同一个,无任何关系,而且block内的people只能读不能写,但是我们可以修改对象的属性
对于成员变量(全局变量,非基本数据类型)或者有)__block修饰的局部非基本数据类型的变量,block内外是同一个值(访问同同一块内存),而且可以对其值进行修改
*/
#pragma mark ==对基本数据类型的影响
/*
block对于基本数据类型的影响
对于没有__block修饰的局部基本数据类型的变量,block内会对其值进行copy(浅),也就是说,block内外的count不是同一个,无任何关系,而且block内的count只能读,不能写,
对于成员变量(全局,基本数据类型)或者有__block修饰的局部基本数据类型的变量,block内外是同有个值(深copy ,访问同一块内存),而且可以对其值进行修改
*/
自定义block块回调
在要传值的.h界面声明一个typedef void ( ^方法名)(类 * 参数名)的block,并写一个返回值类型为id的带参数的自定义方法(不要*);然后在.m文件中实现这个方法,用block的方法名声明一个block接收自定义方法的参数 ,扩大作用域.在要回传的方法中调用block块,回调时()内的参数就是要传的值
在要接收值的界面,在声明界面初始化的时候,调用自定义方法,在方法的block块中接收值.