block總結

1.是什麼?函數

一種特殊的數據類型優化

2.有什麼用?atom

用於保存代碼塊spa

3.怎麼用?code

>1.聲明block的快捷鍵:對象

inlineBlockblog

>2.block的聲明:內存

    <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
        <#statements#>
    };

>3.聲明/初始化/調用it

    //聲明
    void(^myBlock1)();//無參無反
    int(^myBlock2)();//無參有反
    void(^myBlock3)(int);//有參無反
    int(^myBlock4)(int,int);//有參有反

    //初始化
    myBlock1 = ^()
    {
        NSLog(@"無參無反");
    };

    myBlock2 = ^()
    {
        return 3;
    };

    myBlock3 = ^(int a)
    {
        NSLog(@"%d",a);
    };

    myBlock4 = ^(int a,int b)
    {
        return a + b;
    };

    //調用
    myBlock1();
    int num = myBlock2();
    myBlock3(3);
    int sum = myBlock4(3,4);

>4.給block起別名event

返回值類型 (^別名)(參數);

例:

typedef void(^myBlock)();//給第一個無參無反的block起別名myBlock,myBlock就稱爲一種數據類型

使用:

  myBlock block1 = ^(){
        NSLog(@"聲明和定義不一樣,聲明僅僅是聲明一個變量(開闢一塊內存空間),並不初始化,定義包含了初始化,像這樣便是聲明的同時初始化了");
    };

像這樣僅僅是聲明瞭一個myBlock類型的變量:

    myBlock block2;
    myBlock block3;
    myBlock block4;

由於block是一種數據類型,所以數據類型所具備的所用特性block都具備,能夠聲明變量;做爲參數;做爲返回值;

>5.block做爲函數參數

>例一:

typedef int(^myBlock2)();
typedef int(^myBlock3)(int);
 int sum(myBlock2 m,myBlock3 n,int a)//a爲myBlock3須要的參數
{
//    int num1 = m();
//    int num2 = n(a);
//    return num1 + num2;
    return m() + n(a);
}
    //block做爲函數參數
    myBlock2 m = ^(){
        return 10;
    };

    myBlock3 n = ^(int a)
    {
        return a;
    };

    int num = sum(m, n, 10);

    NSLog(@"%d",num);//輸出20;

此種方式並不經常使用.經常使用的情景是:好比有三個函數,開頭和結尾部分執行的代碼同樣,中間有部分代碼不一樣,那麼就能夠將中間部分抽取爲block,將三個函數變爲一個,調用三次該函數,傳入不一樣的block便可.

>例二:

 
void test1() {

    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
    NSLog(@"星期天,今天去哪兒浪呢?");
    
    NSLog(@"BBBBBBBBBBBBBBBBBBBB");
    
    
}

void test2() {
    
    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
    NSLog(@"星期一,昨天玩的好累不想上班.");
    
    NSLog(@"BBBBBBBBBBBBBBBBBBBB");
    
}

void test3() {
    
    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
    NSLog(@"星期二,昨天的任務還沒完成");
    
    NSLog(@"BBBBBBBBBBBBBBBBBBBB");
    
}

經過block優化,分析中間部分代碼,不須要參數,返回值,定義無參無反的block:

typedef void(^myBlock)()

將四個函數抽取爲一個

void test(myBlock myLife) {
    
    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
  if(myLife){//判斷block是否爲nil,不然可能報錯,會報什麼錯呢?,爲何是nil呢,nil不是用於OC對象爲空的狀況麼?block是基本數據類型?仍是OC類型?
myLife();
  } NSLog(
@"BBBBBBBBBBBBBBBBBBBB"); }

main函數中就能夠這樣寫:

 test(^(){
     NSLog(@"星期天,今天去哪兒浪呢?");
 });
 test(^(){
     NSLog(@"星期一,昨天玩的好累不想上班.");
 });
 test(^(){
     NSLog(@"星期二,昨天的任務還沒完成");
 });

>6.做爲函數返回值

typedef void(^myBlock)();

myBlock test4()
{
    return ^(){

    };
}

>7.利用block在不一樣對象間進行傳值

假設A須要傳值給B,那麼須要在A中定義一個block屬性,在須要的時候傳遞值,先判斷是否爲nil,不爲nil則調用block.

須要在B中聲明一個屬性(有東西接收就能夠,不必定就要定義屬性),用以接收傳遞過來的值,B必須拿到A,好比A成爲B的屬性,那麼就能夠獲取A的block屬性,並定義,判斷的時候,block就已經定義了,就能夠實現傳值了.

例子:

控制器的View上有一個綠色的View,當點擊屏幕的時候,傳遞一個NSInteger數據給控制器.

分析:

綠色的View爲數據的傳遞者,控制器爲接收者,所以,須要給綠色的View聲明一個block類型的屬性,所以自定義一個GreenView的類用於描述綠色的View,並在其中聲明block屬性

typedef void(^GreenViewBlock)(NSInteger index);
@property (nonatomic,copy) GreenViewBlock myBlock;

當點擊屏幕的時候傳遞數據,於是重寫touchesBegin方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (_myBlock) {//若是實現了,就調用
        _myBlock(11);
    }
}

控制器爲接收者,於是給控制器聲明一個屬性用於接收數據,又由於,須要在控制器中初始化block,這樣點擊屏幕是block不爲nil,實現傳值,於是須要得到綠色的View的屬性block,於是,將綠色的View拖成控制器的屬性

@property (nonatomic,assign) NSInteger index;

@property (weak, nonatomic) IBOutlet GreenView *greenView;
//初始化block  
_greenView.myBlock = ^(NSInteger index){ self.index = index; };
//上面的賦值操做便是調用index的setter方法,於是此時便可得到傳遞過來的數據
- (void)setIndex:(NSInteger)index { _index = index; NSLog(@"%ld",index); }

>8.注意:

 block內部默認不能修改外部的局部變量

 用__block修飾局部變量,在block中就能夠訪問了.

相關文章
相關標籤/搜索