block 是一組代碼塊組成的特殊類型,在定義和作爲參數時跟普通類型略有不同,
// block :塊代碼.指向結構體的指針.javascript/js:閉包.
// 閉包: 可以從函數外部訪問函數內部的變量.
// block 很靈活. 可以將 block 當做一個參數傳遞.
===> 將一個方法當做參數傳遞了.
// block 使用:
// 1. 定義block類型. 返回值/參數類型.
// 2. 定義block中執行的內容. 確定block中執行的代碼.
// 3. 執行block.
// 上面三步只要保證順序就OK,具體哪一個步驟在哪一個對象中定義,不必關心.
block的定義:
void (^block)(int a,int b) =^(int a,int b){
NSLog(@"%d “,a+b);
};
void 是這個block返回值的類型,^這個符號專門代表block類型的,小括號內的(int a,int b)是參數列表,後面接的是定義後的直接賦值,^是固定寫法,後面接上參數列表,再後面的大括號內寫這個block具體包括的代碼;
直接定義寫法: 返回值類型 (^ block變量名)(參數列表);
block類型可以直接作爲函數的參數或者函數的返回值:
一般比較常見的寫法是typedef void (^block) ();
這樣通過起別名的方式把較爲繁瑣的block類型直接改爲block,此時,定義一個變量名爲bb的無參數無返回值的block類型就可以直接寫:block bb; 其他有參數及有返回值的block均可以通過這種方式來起別名,這樣起別名的好處是可以直接用於函數或是方法中傳入block類型;
例如:
typedef void(^ BlockType) ();
@interface Person :NSObject
@property BlockType bb;
@prtoperty int a;
@end
這裏可以參照 下面的int型來做參考理解,
下面給新手講解兩個特別難理解的寫法:
typedef void(^ BlockType) ();
@interface Person :NSObject
(1) -(void)test :(void (^)()) myblock;
-(void)test :(void (^myblock)()) ;
-(void) test:(BlockType) myblock;
(2): @property void(^block)();
@prtoperty int a;
@end
其中 (1) 是一種特殊的寫法,把myblock作爲參數傳入對象的方法test中,下面兩個傳統寫法作參考
其中(2)是一種常見的定義對象屬性的方式,對比下面的int 類型定義還是有特別區別,新手可以這樣理解,int a 是前面是類型,後面是變量名,也就是說@property需要知道後面的是什麼類型,然後是變量名是什麼,而我們用 @property void(^block)();時,@property已經知道了這個是一個無參數無返回值類型的block,然後這個類型的變量名是block,所以這種寫法是非常正統和正確的,當然也可以像上面的一樣使用typedef起別名的方式來定義。
//下面就給出一個實例
A對象:需要執行一段代碼,但是需要B對象的值
A對象要寫的代碼:(next爲B對象,在A對象中能跟B對象進行交流的代碼中寫一句話,譬如在導航控制器的
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
方法)
next.block = ^(NextController * next){
self.label.text = next.textField.text;
};
//備註:如果在代碼中的NextController * next不寫齊的,系統無法去執行代碼,
B對象要寫的代碼:
.h:
typedef void(^myblock)(NextController *);
@property(nonatomic,strong)myblock block;
.m
if (self.block) {
self.block(self);
}