自從block出現(xiàn)之后,很多API都開始采用這樣的結(jié)構(gòu),由此可見,block確實(shí)有許多優(yōu)勢存在,譬如可以取代協(xié)議,增加程序的可讀性,這里將一些簡單用法總結(jié)如下:
一、如何聲明一個(gè)block變量
我們通過^符號來聲明block類型,形式如下:
void (^myBlock)();
其中第一個(gè)void是返回值,可以是任意類型,中間括號中^后面的是這個(gè)block變量的名字,我把它命名為myBlock,最后一個(gè)括號中是參數(shù),如果多參數(shù),可以寫成如下樣式:
int (^myBlock)(int,int);
同樣,你也可以給參數(shù)起名字:
int (^myBlock)(int a,int b);
很多時(shí)候,我們需要將我們聲明的block類型作為函數(shù)的參數(shù),也有一下幾種方式:
1、-(void)func:(int (^)(int a,int b))block;
第二種方式是通過typedef定義一種新的類型,這也是大多數(shù)情況下采用的方式:
2、typedef int (^myBlock)(int a,int b) ;
-(void)func:(myBlock)block ;
第三種方式也是通過typedef定義,但將blcok包裝重命名成為屬性再調(diào)用,這種思路也更清晰明了
3、typedef void (^myBlock)(int a ,int b);
@property (nonatomic, strong) myBlcok block;
-(void)func:(myBlcok)block;
二、如何實(shí)現(xiàn)一個(gè)block
既然block可以被聲明為變量,那么就一定可以實(shí)現(xiàn)它,就像其他類型變量的賦值。我自己對block的理解為它是一斷代碼塊,所以給它賦值賦便是一段代碼段:
typedef int (^myBlock)(int,int) ;
@interface ViewController ()
{
myBlock block1;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
block1 =^(int a, int b)
{
return a+b;
};
NSLog(@"%d",block1(1,1));
}
這里打印的結(jié)果是2,從這里可以發(fā)現(xiàn)block和函數(shù)的功能很像。
注意:1、在上面的代碼里 block1是一個(gè)對象,如果直接打印將打印對象地址
2、block(),加上后面的括號才是執(zhí)行block語句塊
三、block中訪問對象的微妙關(guān)系
1、如果你在一個(gè)block塊中僅僅訪問對象,而不是對他進(jìn)行修改操作,是沒有任何問題的:
- (void)viewDidLoad {
[super viewDidLoad];
int tem=2;
block1 = ^(int a,int b){
int count= tem+1;
return count;
};
NSLog(@"%d",block1(1,1));
}
而如果我在block塊中直接修改,編譯器會(huì)報(bào)錯(cuò):
block1 = ^(int a,int b){
tem+=1;
return tem+1;
};
為什么會(huì)出現(xiàn)這樣的情況,根據(jù)猜測,可能是block內(nèi)部將訪問的變量都備份了一份,如果我們在內(nèi)部修改,外部的變量并不會(huì)被修改,我們可以通過打印變量的地址來證明這一點(diǎn):
- (void)viewDidLoad {
[super viewDidLoad];
int tem=2;
NSLog(@"%p",&tem);
block1 = ^(int a,int b){
NSLog(@"%p",&tem);
return tem+1;
};
NSLog(@"%d",block1(1,1)); }
打印結(jié)果如下:

可以看出,變量的地址已經(jīng)改變
這是block的簡單聲明是使用的介紹