1. 程式人生 > >block的簡單回撥傳值

block的簡單回撥傳值

由於block的火熱,讓我這個菜鳥也不得不多瞭解一下block的基本用法,雖然我之前用的是protocal代理的方式在頁面之間進行的傳值。但是,block的火熱讓我不得不來寫一個demo學習下,好了廢話不多說。

我所理解的block的簡單用法:

首先借用大家比較熟知的一張圖來解釋下一般的block的樣子,以及各個引數的意義。

按照呼叫函式的方式呼叫塊物件變數就可以了:
int result = myBlock(4); 

 result是 28

。。。。。。。。。

當然對上圖我的理解是,block定義的一種方法,這個方法需要傳入一個int型別的引數,返回值也是一個int型別的數值。而myBlock就是函式的名字,我們在c語言中呼叫一個函式的時候,就是myBlock(4);這樣呼叫,而且用一個int型別的result來接收返回值。

正如c語言中的函式,如果你定義了一個函式,而沒有去呼叫這個函式,那麼這個函式就不會執行(雖然這裡說的不是特別對,但是可以這樣理解)。所以想讓函式執行,那麼我們需要在main函式中去呼叫我們定義的這個函式。

再看下邊的例子:

  1. int global = 1000;  
  2. int main(int argc, constchar * argv[])  
  3. {  
  4.     @autoreleasepool {  
  5.         void(^block)(void) = ^(void)  
  6.         {  
  7.             global++;  
  8.             NSLog(@"global:%d"
    , global);  
  9.         };  
  10.         block();  
  11.         NSLog(@"global:%d", global);  
  12.     }  
  13.     return 0;  
  14. }  
其中global時定義的一個全域性變數,而在block中去呼叫這個變數,並且改變它是可以的,結果都是1001;

而定一個如果是一個區域性變數

  1. int local = 500;  
  2. void(^block)(void) = ^(void)  
  3. {  
  4.       local++;  
  5.     NSLog(@"local:%d", local);  
  6. };  
  7. block();  
  8. NSLog(@"local:%d", local);  
這樣在block中是不可以訪問到這個變數的,會報錯:


那麼,如果我門想訪問這個變數,並且改變它只需要在定義的時候加一個修飾符__block,然後我們就可以訪問並且改變它了。

說了這麼多無非想引入我要說的block的回撥傳值:

在兩個頁面間,當一個頁面A和一個頁面B之間,如果我想的是a中有一個button,點選這個button進入b。但是在b中有一個按鈕,只有我點選b的按鈕時,並且b會傳值給a中的button來顯示。

由於block資料型別的語法會降低整個程式碼的閱讀性,所以常使用typedef來定義block型別。

開始,我搞不懂在哪個裡邊定義block的回撥函式,所以只能死記了。哪個頁面要傳值,哪個頁面來定義這個block的回撥函式。

首先,我知道頁面a中button顯示的東西是頁面b點選按鈕時傳遞過來的,所以按照我記住的就是由頁面b來定義這個block回撥函式。

所以程式碼如下:

#import <UIKit/UIKit.h>

typedef void (^clickButtonCallBack)(NSString *str);

@interface BlockTestViewController : UIViewController

@property (copy, nonatomic) clickButtonCallBack callBack;

@end

我在b頁面定義一個回撥函式,也就是callBack的setter函式。首先定義個block的函式typedefvoid (^clickButtonCallBack)(NSString *str);讓它可以傳遞一個字串型別的引數,沒有返回值。然後為類定義個引數,其中clickButtonCallBack 作為一種型別來定義callBack變數。 一開始也不習慣這種寫法,但是,只要牢記block的基本樣子,還是可以對照著寫出來這個回撥函式的typedefvoid (^clickButtonCallBack)(NSString *str) 然後我們回到頁面b的.m檔案中,在點選事件中:

- (void)clickButton{

    static int num = 0;

    NSString *s = [NSString stringWithFormat:@"點選 %d",num];

    [self.navigationControllerpopViewControllerAnimated:YES];

    if(self.callBack){

        self.callBack(s);

        num++;

    }

}

我做了簡單的處理,定義個num來記錄我點選的次數,其實傳遞的字串就是s,也就是我點選的次數形成的字串

頁面b是由頁面a push進來的,我們現在看頁面a的.m中我做的處理,同樣我在頁面a中有一個按鈕,點選按鈕的事件是:

- (void)clickButton{

    __weak typeof(self) weakSelf = self;

BlockTestViewController *blockTest = [[BlockTestViewControlleralloc] init];

    blockTest.callBack=^(NSString *str){

        [weakSelf.button setTitle:str forState:UIControlStateNormal];

    };

    [self.navigationControllerpushViewController:blockTest animated:YES];

}

其中,BlockTestViewController 便是我說的頁面b,

 blockTest.callBack=^(NSString *str){

        [weakSelf.button setTitle:str forState:UIControlStateNormal];

    };

這裡就是我呼叫block的回撥函式時觸發的事件。str便是頁面b傳過來的引數

經驗證傳值成功。

下邊是全部程式碼:

頁面a中:

.h

#import <UIKit/UIKit.h>

@interface BlockNextViewController : UIViewController

@end

.m

#import "BlockNextViewController.h"

#import "BlockTestViewController.h"

@interface BlockNextViewController ()

@property (nonatomic, weak) UIButton *button;

@end

@implementation BlockNextViewController

- (void)viewDidLoad {

    [superviewDidLoad];

    UIButton *testButton = [UIButton buttonWithType:UIButtonTypeCustom];

    testButton.frame = CGRectMake(100, 400, 100, 40);

    [testButton setTitle:@"click"forState:UIControlStateNormal];

    [testButton addTarget:selfaction:@selector(clickButton) forControlEvents:UIControlEventTouchUpInside];

    _button = testButton;

    testButton.backgroundColor = [UIColor redColor];

    [self.view addSubview:testButton];

    // Do any additional setup after loading the view.

}

- (void)clickButton{

   __weak typeof(self) weakSelf = self;

   BlockTestViewController *blockTest = [[BlockTestViewController alloc] init];

    blockTest.callBack=^(NSString *str){

        [weakSelf.button setTitle:str forState:UIControlStateNormal];

    };

    [self.navigationControllerpushViewController:blockTest animated:YES];

}

頁面b中:

.h

#import <UIKit/UIKit.h>

typedef void (^clickButtonCallBack)(NSString *str);

@interface BlockTestViewController : UIViewController

@property (copy, nonatomic) clickButtonCallBack callBack;

@end


.m

#import "BlockTestViewController.h"

@interface BlockTestViewController ()

@property (nonatomic, weak) UIButton *testButton;

@end

@implementation BlockTestViewController

- (void)viewDidLoad {

    [superviewDidLoad];

    UIButton *testButton = [UIButton buttonWithType:UIButtonTypeCustom];

    testButton.frame = CGRectMake(100, 400, 100, 40);

    [testButton setTitle:@"click"forState:UIControlStateNormal];

    [testButton addTarget:selfaction:@selector(clickButton) forControlEvents:UIControlEventTouchUpInside];

    testButton.backgroundColor = [UIColor redColor];

    _testButton = testButton;

    [self.view addSubview:testButton];

    // Do any additional setup after loading the view.

}

- (void)clickButton{

   static int num = 0;

     NSString *s = [NSString stringWithFormat:@"點選 %d",num];

    [self.navigationController popViewControllerAnimated:YES];

    if(self.callBack){

        self.callBack(s);

        num++;

    }

}