天天看點

Block回調了解

block應用執行個體如下:https://blog.csdn.net/huangfei711/article/details/73928495

Block循環引用的問題:

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

代碼 

self.label.text = text;

 ,在 Block 中引用 self ,也就是 A ,而 A 建立并引用了 B ,而 B 引用 

callBackBlock

,此時就形成了一個循環引用,而編譯器也不會報任何錯誤,此時使用弱引用解決這個問題。

- (IBAction)ABtn:(UIButton *)sender {
    __weak typeof(self) weakSelf = self;
    BViewController *BVC = [[BViewController alloc] init];
    BVC.backBlock = ^(NSString *text) {
        weakSelf.ATextLabel.text = text;
    };
    [self presentViewController:BVC animated:true completion:nil];
}
           

我們都知道 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 塊就可以擷取到值。雖然思路是對的,但其實是不完整,導緻我們形成了回調的資料是通過某種底層實作傳遞過去的錯覺,這就使得我們認為這不需要深究。

事實是,通過簡單的整理我們可以發現完整的回調流程應該是這樣的:

  1. block 代碼塊指派給 

    bVC.callBackBlock

    ,此時 

    callBackBlock

     的指針就指向這個代碼塊。
  2. 調用 

    callBackBlock(NSString *text)

  3. 由于 

    callBackBlock

     的指針是指向 A 中的 block 代碼塊,是以執行代碼塊的代碼,實作回調。

    很顯然之前我忽略了代碼塊指派給 

    callBackBlock

     的這個操作(羞愧)。

    現在再通過一段代碼可以更清晰地了解這個原理:

    bVC.callBackBlock = ^(NSString *text){ //1
            NSLog(@"text is %@",text);
        };
      bVC.callBackBlock = ^(NSString *text){ //2
            NSLog(@"text b is %@",text);
        };
               
    上述代碼中,我們對 

    callBackBlock

    進行了兩次指派,結果會怎麼樣呢?可以看出來,Block 的回調隻對代碼 2 生效,因為

    callBackBlock

    的指針最後指向了代碼 2 的代碼塊。是以并沒有什麼神奇的魔法,也沒什麼隐藏的底層機制(這裡指的是友善了解的底層)讓你可以帶着疑惑去使用它。