block淺析

Block 的本質(zhì)是可以截取自動變量的匿名函數(shù)。

一.block的三種定義方式

1.返回值類型(^block的名字)(參數(shù)類型) = ^(參數(shù)類型和參數(shù)名) {};

void(^block)() = ^(){

NSLog(@"調(diào)用了block");

};

2.//返回值類型(^block的名字)(參數(shù)類型) = ^(參數(shù)類型和參數(shù)名) {};

//如果有參數(shù),定義的時候,必須要寫參數(shù),而且必須要有參數(shù)變量名

int(^block)(int) = ^(int a){

return 1;

};

3.系統(tǒng)提供了一個定義block的宏

returnType(^blockName)(parameterTypes) = ^(parameters) {

//? ? ? ? statements

//? ? };

二.block類型

@property (nonatomic, strong) void(^block)();//這樣在類中可以拿到self.block

//當(dāng)然也可以取別名:

typedef void(^BlockType)();//BlockType不是變量名,而是這種類型的block的別名

//然后就可以這樣

@property (nonatomic, strong) BlockType block;

三.block變量的傳遞

(1)如果是局部變量,Block是值傳遞

(2)如果是靜態(tài)變量,全局變量,__block修飾的變量,block都是指針傳遞


@property (nonatomic, strong) CompletionBlock zfbBlock;

//block只能使用strong,不要使用copy

//因?yàn)楫?dāng)使用copy的時候,set方法是調(diào)用了copy幫你深拷貝一次,沒有這個必要.

//就像NSString一樣,他一般都是@"a"這種常量,沒必要再去深拷貝一次,所以NSString常量也用strong不用copy.

__weak typeof (&*self) weakSelf= self;

/*

因?yàn)閎lock會給內(nèi)部的強(qiáng)指針對象進(jìn)行一次強(qiáng)引用,比如常見的傳入block中的self進(jìn)行強(qiáng)引用

并且在self中,block又是strong的,self對block是強(qiáng)引用

所以,你強(qiáng)引用我,我強(qiáng)引用你,誰也不會被釋放,就造成了循環(huán)引用

所以,為了避免循環(huán)引用,我們要在block使用self之前,進(jìn)行這一步操作:

在block中使用weakSelf,就不會產(chǎn)生循環(huán)引用問題了.

使用了__weak修飾符的對象,作用等同于定義為weak的property。自然不會導(dǎo)致循環(huán)引用問題.

*/


Block 回調(diào)實(shí)現(xiàn)

首先解釋一下我們例子要實(shí)現(xiàn)什么功能(其實(shí)是爛大街又最形象的例子):

有兩個視圖控制器 A 和 B,現(xiàn)在點(diǎn)擊 A 上的按鈕跳轉(zhuǎn)到視圖 B ,并在 B 中的textfield 輸入字符串,點(diǎn)擊 B 中的跳轉(zhuǎn)按鈕跳轉(zhuǎn)回 A ,并將之前輸入的字符串

顯示在 A 中的 label 上。也就是說 A 視圖中需要回調(diào) B 視圖中的數(shù)據(jù)。

我們可以簡單地這樣思考,需要回調(diào)數(shù)據(jù)的是 A 視圖,那么 Block 就應(yīng)該在 B 中定義,用于獲取傳入回調(diào)數(shù)據(jù)。

因此我們在 BViewController.h 中定義如下:

//BViewController.h#import

typedefvoid(^CallBackBlcok(NSString*text);

//1@interfaceBViewController:UIViewController

@property(nonatomic,copy)CallBackBlcok callBackBlock;//2

@end

在這里,代碼 1 用 typedef 定義了void(^) (NSString *text)的別名為CallBackBlcok。這樣我們就可以在代碼 2 中,使用這個別名定義一個 Block 類型的變量callBackBlock。

在定義了callBackBlock之后,我們可以在 B 中的點(diǎn)擊事件中添加callBackBlock的傳參操作:

//BViewController.m

- (IBAction)click:(id)sender {

self.callBackBlock(_textField.text);//1[

self.navigationControllerpopToRootViewControllerAnimated:YES];}

這樣我們就可以在想要獲取數(shù)據(jù)回調(diào)的地方,也就 A 的視圖中調(diào)用 block:

// AViewController.m

- (IBAction)push:(id)sender {?

? BViewController *bVC = [self.storyboardinstantiateViewControllerWithIdentifier:@"BViewController"];? ? bVC.callBackBlock= ^(NSString*text){

// 1NSLog(@"text is %@",text);

self.label.text= text;? ?

};? ?

[self.navigationControllerpushViewController:bVC animated:YES];}

代碼 1 中,通過對回調(diào)將 B 中的數(shù)據(jù)傳遞到代碼塊中,并賦值給 A

中的 label,實(shí)現(xiàn)了整個回調(diào)過程。

上例是通過將 block 直接賦值給 block 屬性,也可以通過方法參數(shù)的方式傳遞 block 塊。


關(guān)于 Block 的疑惑

到目前為止,一切看起來都很美好(如果你照著上面的例子做的話),功能正常, A 視圖中也獲取到數(shù)據(jù)了。但是某些人可能就要說了,你的代碼有問題,你的思路有問題,你這是誤人子弟。

是的,代碼的確還有問題,第一個問題就是循環(huán)引用的問題,在 A 視圖的block 代碼塊中:

bVC.callBackBlock= ^(NSString*text){NSLog(@"text is %@",text);self.label.text= text;? ? ? ? ? };

代碼self.label.text = text;,在 Block 中引用 self ,也就是 A ,而 A 創(chuàng)建并引用了 B ,而 B 引用callBackBlock,此時就形成了一個循環(huán)引用,而編譯器也不會報任何錯誤,我們需要非常小心這個問題(面試百分百問到我會亂說?)。此時我們通常的解決方法是使用弱引用來解除這個循環(huán):

__weakAViewController*weakSelf =self;? ? bVC.callBackBlock= ^(NSString*text){NSLog(@"text is %@",text);//? ? ? ? self.label.text = text;weakSelf.label.text= text;? ? };

第二個問題是我自己對 Block 的理解不到位,我們都知道 Block 能截取自動變量,并且是不能在 Block 塊中進(jìn)行修改的(除非用__block修飾符),但是很明顯weakSelf.label.text的值被修改了,并且沒有用__block修飾符, 這是為什么呢?因?yàn)閘abel是個全局變量,而如果像如下的局部變量a是不能修改的,編譯器也會報錯:

局部變量

通過這個小例子發(fā)現(xiàn)的兩個問題,也算是值得了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Block 的使用有兩種:1.獨(dú)立Block 。2.內(nèi)聯(lián)Block 。 《一》獨(dú)立Block 使用方式 一、定義一...
    鄉(xiāng)村小子閱讀 348評論 0 0
  • 對block的了解不是特別多,平常用代理用的比較多; Block寫法:^(傳入?yún)?shù)列){行為主體};Block實(shí)體...
    阿基米敬閱讀 416評論 3 3
  • block是語言的的擴(kuò)展功能,它是一種帶有自動變量(局部變量)的匿名函數(shù). /******************...
    long2016閱讀 270評論 0 1
  • 剛剛落下帷幕的第89屆奧斯卡以兩段獲獎感言的烏龍事件喜淚收官,幾家歡喜幾家愁,惡搞和唏噓聲在網(wǎng)絡(luò)上的聲勢絕對不亞于...
    一碗甜椒閱讀 1,339評論 0 0
  • 學(xué)習(xí),模仿,如初來乍到 我欣賞你克服了心魔那一刻,但我忘記了獎賞你,對不起我忽視你了,我只會命令你去追趕別人的腳步...
    在努力生活的小姑娘閱讀 172評論 0 1

友情鏈接更多精彩內(nèi)容