基础知识:
1)block声明,block创建,block调用。
//block声明
int (^myBlock)(int);
//block创建
myBlock = ^(int a){
int result = a*a;
return c;
};
//block调用
myBlock(10);
2)声明一个block参数
(void)objectMethod:(int (^)(int))block;
或者:typedef int (^MyBlock)(int);
(void)objectMethod:(MyBlock )block;
3)创建block实现,作为参数传递
[self objectMethod:^(int a,int b){
return a+b;
}];
4)block的内存管理
<1> block按照作用域可以分为全局变量和局部变量
block代码里面可以引用全局变量和局部变量,但是有不同的管理机制。
<2> block引用局部变量时,该变量可以作为常量编码到block代码块中。
__block int number =10;
myBlock =^(int a){
number = 20;
};
<3> block里面引用一个局部的Object-C对象时候,该对象会retain;
如果局部变量用__block修饰,则不会retain;
NSObject *object = [[NSObject alloc] init];
[self objectMethod:^(int a,int b){
NSLog(@“计数:%d”,object.retainCount);//引用计数为2;
}];
__block NSObject *object = [[NSObject alloc] init];//引用计数为1;
<4> 在block代码块里面引用一个实例变量时,该实例对象会被retain;
NSLog(@“计数:%d”,self.retainCount);//引用计数为1;
[self objectMethod:^(int a,int b){
int value = number;//number为全局变量
NSLog(@“计数:%d”,self.retainCount);//引用计数为2;
return a+b;
}];
<5>block本身可以像对象一样copy和release;
block创建之后内存是分配在栈上,调用copy方法,会把block从栈上移到堆上。两种copy方法
[__block copy];//方法一
Block_copy(__block);//方法二
两种release方法
[__block release];
Block_release(__block);
5)block引用了一个实例变量,实例变量会被retain。很容易造成循环引用。
案例:想点击任何一个底部菜单的button都通知顶部菜单,顶部菜单想做的事情交给底部菜单去做,顶部菜单想在底部菜单隐藏的时候做点东西。顶部菜单想做的事情顶部菜单最清楚,所以防在它那里写block。
分析*************
问题:底部菜单点击了遮盖,想取消选中顶部菜单的button.
(1)在顶部菜单.m文件中 ——————顶部菜单想做的事情顶部菜单最清楚
底部菜单已经点击遮盖情况下,顶部菜单想做的事情如下
{
//1.取消选中当前的item
menu->_selectedItem.selected = NO;
menu->_selectedItem = nil;
// 2.清空正在显示的菜单
menu->_showingMenu = nil;
}
把{}里面那段代码放在底部菜单-(void)hide那里调用。
{}里面有变量是底部菜单没有的,所有这时候就要把{}那段代码封装成Block,在底部菜单调用了。
(2)在底部菜单.m文件中
设置一个block,接收顶部菜单信息。block要用copy
@property(nonatomic,copy) void(^hideBlock)();//放在底部菜单.h
if(_hideBlock){
_hideBlock();
}
(3)在顶部菜单.m文件中
_showingMenu.hideBlock = ^{
// 1.取消选中当前的item
menu->_selectedItem.selected = NO;
menu->_selectedItem = nil;
// 2.清空正在显示的菜单
menu->_showingMenu = nil;
};