Block 回調完成
先隨著我完成最簡略的 Block 回調傳參的應用,假如你能觸類旁通,根本上可以知足了 OC 中的開辟需求。曾經完成的同窗可以跳到下一節。
起首說明一下我們例子要完成甚麼功效(實際上是爛年夜街又最抽象的例子):
有兩個視圖掌握器 A 和 B,如今點擊 A 上的按鈕跳轉到視圖 B ,並在 B 中的textfield 輸出字符串,點擊 B 中的跳轉按鈕跳轉回 A ,並將之前輸出的字符串
顯示在 A 中的 label 上。也就是說 A 視圖中須要回調 B 視圖中的數據。
想不明確的同窗可以看一看終究完成的後果圖:
這裡不再對 Block 的語法做解釋了。
起首,我們須要界說兩個試圖掌握器 AViewController
和 BViewController
,如今我們須要思慮一下,Block 應當在哪裡界說呢?
我們可以簡略地如許思慮,須要回調數據的是 A 視圖,那末 Block 就應當在 B 中界說,用於獲得傳入回調數據。
是以我們在 BViewController.h
中界說以下:
//BViewController.h #import <UIKit/UIKit.h> typedef void(^CallBackBlcok) (NSString *text);//1 @interface BViewController : UIViewController @property (nonatomic,copy)CallBackBlcok callBackBlock;//2 @end
在這裡,代碼 1 用 typedef 界說了 void(^) (NSString *text)
的別號為 CallBackBlcok
。如許我們便可以在代碼 2 中,應用這個體名界說一個 Block 類型的變量 callBackBlock
。
在界說了 callBackBlock
以後,我們可以在 B 中的點擊事宜中添加 callBackBlock
的傳參操作:
//BViewController.m - (IBAction)click:(id)sender { self.callBackBlock(_textField.text); //1 [self.navigationController popToRootViewControllerAnimated:YES]; }
如許我們便可以在想要獲得數據回調的處所,也就 A 的視圖中挪用 block:
// AViewController.m - (IBAction)push:(id)sender { BViewController *bVC = [self.storyboard instantiateViewControllerWithIdentifier:@"BViewController"]; bVC.callBackBlock = ^(NSString *text){ // 1 NSLog(@"text is %@",text); self.label.text = text; }; [self.navigationController pushViewController:bVC animated:YES]; }
代碼 1 中,經由過程對回調將 B 中的數據傳遞到代碼塊中,並賦值給 A中的 label,完成了全部回調進程。
上例是經由過程將 block 直接賦值給 block 屬性,也能夠經由過程辦法參數的方法傳遞 block 塊。
關於 Block 的困惑
到今朝為止,一切看起來都很美妙(假如你照著下面的例子做的話),功效正常, A 視圖中也獲得到數據了。然則某些人能夠就要說了,你的代碼有成績,你的思緒有成績,你這是誤人後輩。
是的,代碼切實其實還有成績,第一個成績就是輪回援用的成績,在 A 視圖的block 代碼塊中:
bVC.callBackBlock = ^(NSString *text){ NSLog(@"text is %@",text); self.label.text = text; };
代碼 self.label.text = text;
,在 Block 中援用 self ,也就是 A ,而 A 創立並援用了 B ,而 B 援用 callBackBlock
,此時就構成了一個輪回援用,而編譯器也不會報任何毛病,我們須要異常當心這個成績(面試百分百問到我會胡說?)。此時我們平日的處理辦法是應用弱援用來消除這個輪回:
__weak AViewController *weakSelf = self; bVC.callBackBlock = ^(NSString *text){ NSLog(@"text is %@",text); // self.label.text = text; weakSelf.label.text = text; };
第二個成績是我本身對 Block 的懂得不到位,我們都曉得 Block 能截取主動變量,而且是不克不及在 Block 塊中停止修正的(除非用__block潤飾符),然則很顯著 weakSelf.label.text
的值被修正了,而且沒有效__block
潤飾符, 這是為何呢?由於 label 是個全局變量,而假如像以下的部分變量 a 是不克不及修正的,編譯器也會報錯:
部分變量
經由過程這個小例子發明的兩個成績,也算是值得了。
Block 為何能完成奇異的回調
在這裡我不會說甚麼完成道理,僅僅是小我對 Block 能完成奇異回調的懂得,有毛病的處所請年夜家指出。
在先前應用 Block 的進程中,固然會應用,然則老是有一個困惑,簡略說來就是:
為何在 A 中的 block 塊能挪用到 B 中的數據?
回想一下我們在 B 中所完成的代碼,不過乎界說了一個 Block 變量,並在恰當的時刻傳入參數,那末為何在挪用了 self.callBackBlock(_textField.text)
以後,值就奇異傳到了 A 中的 Block 塊了呢?
經由過程整頓應用的進程,我發明是我們的思想墮入了誤區(能夠是我小我),我們以為在 B 中傳入 _textField.text
參數以後, A 中的 Block 塊便可以獲得到值。固然思緒是對的,但實際上是不完全,招致我們構成了回調的數據是經由過程某種底層完成傳遞曩昔的錯覺,這就使得我們以為這不須要深究。
現實是,經由過程簡略的整頓我們可以發明完全的回調流程應當是如許的:
回調流程
block 代碼塊賦值給 bVC.callBackBlock
,此時 callBackBlock
的指針就指向這個代碼塊。
挪用 callBackBlock(NSString *text)
因為 callBackBlock
的指針是指向 A 中的 block 代碼塊,是以履行代碼塊的代碼,完成回調。
很明顯之前我疏忽了代碼塊賦值給 callBackBlock
的這個操作(慚愧)。
如今再經由過程一段代碼可以更清楚地輿解這個道理:
bVC.callBackBlock = ^(NSString *text){ //1 NSLog(@"text is %@",text); }; bVC.callBackBlock = ^(NSString *text){ //2 NSLog(@"text b is %@",text); };
上述代碼中,我們對 callBackBlock
停止了兩次賦值,成果會怎樣樣呢?
two block
可以看出來,Block 的回調只對代碼 2 失效,由於callBackBlock
的指針最初指向了代碼 2 的代碼塊。所以並沒有甚麼奇異的魔法,也沒甚麼隱蔽的底層機制(這裡指的是便利懂得的底層)讓你可以帶著困惑去應用它。
總結
我這小我進修辦法,總結起來就是看到新技巧,先在本身的代碼裡跑一遍,能跑通,而且應用起來沒有甚麼難度,就根本不會深究了。然則自我反思過,如許的進修辦法是很纰謬的,寫代碼不克不及囫囵吞棗,假如想要有所沖破,不想局限於碼農,必定要深刻探討一下完成的機制,最最少要包管不帶著困惑去應用。以上就是這篇文章的全體內容,願望能對年夜家的進修或許任務帶來必定的贊助,假如有疑問年夜家可以留言交換。
【iOS中Block的回調應用息爭析詳解】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!