
###1、block的简单用法
- 无参无返回的block
void(^WBBlock1)()=^(){
NSLog(@"WBBlock1");
};
WBBlock1();
- 有参有返回的block
int (^WBBlock2)(int)=^(int num){
return num;
};
WBBlock2(2);
- 有参无返回的block
void (^WBBlock3)(int)=^(int num){
NSLog(@"%d",num);
};
WBBlock3(3);
###2、利用block在界面传值 我们接下来通过一个WBNavagationView的类来传递点击事件 下面代码是在主页面MainViewController调用WBNavagationView实例来传递点击事件
_navagationView=[[WBNavagationView alloc]init];
__weak MainViewController *weakSelf = self;
[_navagationView addLeftClick:^(int num){//第一步:主界面定义需要被回调的代码块
NSLog(@"%d",num);
}];
WBNavagationView.m文件中的代码
typedef void (^BtnBlock)(int num);//第二步:定义BtnBlock类型的block块
@interface WBNavagationView: UIView
{
BtnBlock _buttonBlock;//第三步:BtnBlock定义相应的代码块
}
@property(strong,readonly,nonatomic)UIButton *button;
-(void)addLeftClick:(BtnBlock)btnBlock;//第四步:将第一步主界面定义代码块赋值给第三步定义代码块
@end
WBNavagationView.h文件中的具体实现block传值代码
- (instancetype)init
{
self = [super init];
if (self) {
//定义button用来出发第一步中主界面MainViewController中定义的代码块
button =[[UIButton alloc]initWithFrame:CGRectMake(100, 100, 60, 30)];
[button addTarget:self action:@selector(BtnClick:) forControlEvents:UIControlEventTouchUpInside];
_leftButton.tag=0;
[self addSubview: button];
}
return self;
}
-(void)addLeftClick:(BtnBlock)btnBlock
{
_ btnBlock = btnBlock;//第四步:接收第一步主界面传递的点击事件代码块
}
-(void)BtnClick:(UIButton *)btn
{
_btnBlock(6);//第五步:点击button回调第一步主界面定义代码块
}
大概过程就是MainViewController中定义代码块传递给WBNavagationView,WBNavagationView接收代码块后适当的时候回调主界面代码块将值传递过去。
###3、block如何避免循环引用 Blocks可以访问局部变量,但是不能修改 如果修改局部变量,需要加__block
__block int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
multiplier ++;//这样就可以了
return num * multiplier;
};
如果局部变量是数组或者指针的时候只复制这个指针,两个指针指向同一个地址,block只修改指针上的内容。如:
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@"a",@"b",@"abc",nil];
NSMutableArray *mArrayCount = [NSMutableArray arrayWithCapacity:1];
[mArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock: ^(id obj,NSUInteger idx, BOOL *stop){
[mArrayCount addObject:[NSNumber numberWithInt:[obj length]]];
}];
NSLog(@"%@",mArrayCount);
例子里面确实没有修改mArrayCount这个局部变量啊。mArrayCount是一个指针,指向一个可变长度的数组。在block里面,并没有修改这个指针,而是修改了这个指针指向的数组。换句话说,mArrayCount是一个整数,保存的是一块内存区域的地址,在block里,并没有改变这个地址,而是读取出这个地址,然后去操作这块地址空间的内容。 这是允许的,因为声明block的时候实际上是把当时的临时变量又复制了一份,在block里即使修改了这些复制的变量,也不影响外面的原始变量。即所谓的闭包。 但是当变量是一个指针的时候,block里只是复制了一份这个指针,两个指针指向同一个地址。所以,在block里面对指针指向内容做的修改,在block外面也一样生效。
_weak _typeof(&*self)weakSelf =self; 等同于_weak UIViewController *weakSelf =self;
总结: 1._block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。 2._weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。 3._block对象可以在block中被重新赋值,_weak不可以。 PS:_unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的_weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。
结语:小伙伴们觉得还行就给点个赞吧^_^