block,指向结构体的指针,同时也相当于结构体+回调函数。
block的定义本质和函数一样,只不过不需要返回函数名。block以签名字符串开始:
^double(double rate,double time){
};
标示返回一个double,以及接受两个同样为double的参数。
void(^block)(int a,int b)=^void(int a,int b){};
-----------> void (^block)( int a, int b);block=^void(int a,int b){};理解:
void(^block)(int a,int b)=^void(int a,int b){};
------->
typedefvoid(^MyBlock)(int,int);//将void(^)(int,int)改MyBlock
MyBlock block=^void(int a,int b){};
最简:无参数无返回值: void (^block)( )=^ {};
传值:
1.定义Block属性;
例:
@property(nonatomic,copy)void(^childBlock)(NSInteger a);
2.参数加入(传值)(同类)
例:
self.childBlock(self.clean);
3.调用set
例:外类:
self.child.childBlock=^(NSInteger a){
NSLog(@"--------------a%ld",a);
};
同类:
self.childBlock=^(NSInteger a){
NSLog(@"cleanSelf%ld",a);
};
回调:
1.定义Block属性(1.m)
例:
@property(nonatomic,copy)void(^childBlock)(NSInteger a);
2.定义方法(1.m)(关联Block属性)
-(void)cleanWithclean:(NSInteger)clean andChildBlock:(void(^)(NSInteger a))childBlock;
{
_clean=clean;
_childBlock=childBlock;
}
3.调用2方法(2.m),回1.m
[self.childcleanWithclean:100andChildBlock:^(NSInteger a) {
NSLog(@"happy-----%ld",a);
}];
此时后面的block不走。
4.后续加入(1.m)(传值,另方法或条件中)
if (self.clean<90) {
self.childBlock(self.happy);//此条件或者方法中走到此处,执行block
}
5.走Block(2.m)
其实跟传值的道理是一样的,(携带参数)执行到block的时候,程序回去找set(程序执行到此,需要有一个block,而不是一个空的东西,所以带着参数去找他的内容所在)。
最后,注意:
1.block使用copy是MRR遗留下来的习惯,ARC中可用strong(ARC默认在堆上),相当于copy;
Block回调特性使Block会对其内部的引用对象或者引用属性的对象Retain一次,导致内存泄露。(copy造成强引用)
所以,引用前在外部需用_ _weak修饰转换一下。例: __weakChild *weakSelf=self;
进入block之后:Child *strongSelf=weakSelf;
即:以弱引用引进来,进来之后再转为强引用使用。
2.block捕获的局部变量(镜像拷贝)存在于block所在的堆中,block内定义的变量位于block函数栈中;
MRR(Manual Retain-Release)时代,_ _block两个作用:a.变量可改;b.指针指向的对象不做隐式retain操作;
ARC(Automatic Reference Counting)时代,_ _block仅能说明可改。
3.static变量和全局变量不用修饰亦可修改