Block的简单使用

序言

block:简单来说就是一段代码块,block里面存在可执行代码,可以在函数内进行使用;也可以作为函数中形参进行使用;最常用的应该是替换delegate来进行回调或者传值.

注意:block只是声明和保留了一段代码块,必须要调用才会执行里面的代码.

基本结构

block结构:返回值类型(^Block名字)(参数列表);

//
void(^myBlock)(NSString *) = ^( NSString * n1){  
 NSLog(@"block");  
}  
(void)表示的是返回值,^:block的标示符,myBlock:这个block块的名称,(NSString * )表示形参.  
调用:myBlock(@"124");  

基本用法

//无参数无返回值
void(^myBlock2)(void) = ^{
    SPLog(@"come on 2");
};
myBlock2();
//有参数无返回值
void(^myBlock1)(NSString *,NSUInteger) = ^(NSString *n1,NSUInteger i1){
    SPLog(@"come on 1 - %@,%ld",n1,i1);
};
myBlock1(@"2b_block",2);
//有参数有返回值
NSString *(^myBlock3)(NSString *) = ^(NSString *n1){
    return [n1 stringByAppendingString:@"-143"];
};
NSString * bn1 = myBlock3(@"341");
SPLog(@"%@",bn1);

修改局部变量

block内是不能直接修改block外变量的值的.
如果需要修改,被修改的变量必须用__block来修饰(注意是2个”_“).

 //修改局部变量
__block NSUInteger i2 = 10;
void(^myBlock4)(NSUInteger) = ^(NSUInteger i3){
    i2 = i3 + 10;
    SPLog(@"block 内i2 = %ld",i2);
};
SPLog(@"block 外i2 = %ld",i2);
myBlock4(i2);

避免循环引用

在类:Block1ViewController中存在2个变量.

//  
@property(nonatomic,copy)void(^b1)(void);  
@property(nonatomic,strong)NSString * myName;  

在类:ViewController中viewDidLoad调用:

   //避免循环引用
Block1ViewController * b1VC = [[Block1ViewController alloc]init];
b1VC.myName = @"b1-block";
__weak typeof(b1VC) weakObjB = b1VC;
b1VC.b1 = ^(){
    NSString * myName = weakObjB.myName;
    SPLog(@"%@",myName);
};
b1VC.b1();

b1VC需要__weak typeof(b1VC) weakObjB = b1VC;使用__weak进行修饰.

简单说明:
首先,b1是Block1ViewController拥有的一个属性,因此Block1ViewController对b1是强引用的;其次,b1对代码块中的属性也是强引用的;所以会导致他们之间相互强引用,从而导致循环引用.

作为函数参数

在类Block1ViewController.h中声明:
-(void)common_from:(void (^)(id message))success;
在类Block1ViewController.m中实现:

//
-(void)common_from:(void (^)(id message))success{
 success(@"come from");
}  

在类:ViewController中viewDidLoad调用:

 //作为参数使用
Block1ViewController * b2VC = [[Block1ViewController alloc]init];
[b2VC common_from:^(id message) {
    SPLog(@" -- %@",message);
}];

这一步其实已经实现了值在2个不同类之间传递,但是传递的值有局限性,只能在当前函数里面进行回调,好处是书写较方便.

typedef结合使用

有时候,我们需要声明多个参数值的时候,需要重复编写,而结合typedef可以简化block使用;好处是可以在类的任何方法里面进行回调,但是书写较麻烦.

//.h文件
#import <UIKit/UIKit.h>
typedef void(^nameColor)(void);
@interface Block1ViewController : UIViewController
@property(nonatomic,copy)nameColor name1;
-(void)typedef_from:(nameColor )m1;
@end  

//.m文件  
#import "Block1ViewController.h"
@implementation Block1ViewController
-(void)typedef_from:(nameColor )m1{
   self.name1 = m1;
}
-(void)touchesBegan:(NSSet<UITouch * > * )touches withEvent:(UIEvent *)event{
   self.name1();//可以在任何函数内进行调用.
   [self dismissViewControllerAnimated:YES completion:nil];
}

一样可以实现类之间的值的传递和delegate协议的处理.